Merge branch 'master' into feature/Moar-patch-bank-support-part3
This commit is contained in:
commit
80e8a3155c
|
|
@ -318,6 +318,8 @@ src/engine/platform/sound/vrcvi/vrcvi.cpp
|
||||||
|
|
||||||
src/engine/platform/sound/scc/scc.cpp
|
src/engine/platform/sound/scc/scc.cpp
|
||||||
|
|
||||||
|
src/engine/platform/oplAInterface.cpp
|
||||||
|
src/engine/platform/ym2608Interface.cpp
|
||||||
src/engine/platform/ym2610Interface.cpp
|
src/engine/platform/ym2610Interface.cpp
|
||||||
|
|
||||||
src/engine/blip_buf.c
|
src/engine/blip_buf.c
|
||||||
|
|
@ -352,6 +354,7 @@ src/engine/platform/c64.cpp
|
||||||
src/engine/platform/arcade.cpp
|
src/engine/platform/arcade.cpp
|
||||||
src/engine/platform/tx81z.cpp
|
src/engine/platform/tx81z.cpp
|
||||||
src/engine/platform/ym2203.cpp
|
src/engine/platform/ym2203.cpp
|
||||||
|
src/engine/platform/ym2608.cpp
|
||||||
src/engine/platform/ym2610.cpp
|
src/engine/platform/ym2610.cpp
|
||||||
src/engine/platform/ym2610ext.cpp
|
src/engine/platform/ym2610ext.cpp
|
||||||
src/engine/platform/ym2610b.cpp
|
src/engine/platform/ym2610b.cpp
|
||||||
|
|
@ -371,6 +374,7 @@ src/engine/platform/lynx.cpp
|
||||||
src/engine/platform/su.cpp
|
src/engine/platform/su.cpp
|
||||||
src/engine/platform/swan.cpp
|
src/engine/platform/swan.cpp
|
||||||
src/engine/platform/vera.cpp
|
src/engine/platform/vera.cpp
|
||||||
|
src/engine/platform/zxbeeper.cpp
|
||||||
src/engine/platform/bubsyswsg.cpp
|
src/engine/platform/bubsyswsg.cpp
|
||||||
src/engine/platform/n163.cpp
|
src/engine/platform/n163.cpp
|
||||||
src/engine/platform/pet.cpp
|
src/engine/platform/pet.cpp
|
||||||
|
|
|
||||||
10
TODO.md
10
TODO.md
|
|
@ -5,11 +5,7 @@
|
||||||
- input pad
|
- input pad
|
||||||
- settings
|
- settings
|
||||||
- RF5C68 system
|
- RF5C68 system
|
||||||
- OPN system
|
- ZX beeper system overlay percussion
|
||||||
- OPNA system
|
|
||||||
- ZX beeper system
|
|
||||||
- Y8950 system
|
|
||||||
- maybe YMU759 ADPCM channel
|
|
||||||
- ADPCM chips
|
- ADPCM chips
|
||||||
- Game Boy envelope macro/sequence
|
- Game Boy envelope macro/sequence
|
||||||
- rewrite the system name detection function anyway
|
- rewrite the system name detection function anyway
|
||||||
|
|
@ -20,11 +16,9 @@
|
||||||
- try to find out why does VSlider not accept keyboard input
|
- try to find out why does VSlider not accept keyboard input
|
||||||
- finish lock layout
|
- finish lock layout
|
||||||
- if macros have release, note off should release them
|
- if macros have release, note off should release them
|
||||||
- add ability to select entire row when clicking on row number
|
|
||||||
- store edit/followOrders/followPattern state in config
|
|
||||||
- add ability to select a column by double clicking
|
- add ability to select a column by double clicking
|
||||||
- add ability to move selection by dragging
|
- add ability to move selection by dragging
|
||||||
- Apply button in settings
|
- Apply button in settings
|
||||||
- find and replace
|
- find and replace
|
||||||
- finish wave synth
|
- finish wave synth
|
||||||
- add mono/poly note preview button
|
- add mono/poly note preview button
|
||||||
|
|
|
||||||
|
|
@ -17,6 +17,7 @@ this is a list of systems that Furnace supports, including each system's effects
|
||||||
- [Yamaha YM2612 standalone](ym2612.md)
|
- [Yamaha YM2612 standalone](ym2612.md)
|
||||||
- [Yamaha YM2151 standalone](ym2151.md)
|
- [Yamaha YM2151 standalone](ym2151.md)
|
||||||
- [SegaPCM](segapcm.md)
|
- [SegaPCM](segapcm.md)
|
||||||
|
- [Capcom QSound](qsound.md)
|
||||||
- [Atari 2600](tia.md)
|
- [Atari 2600](tia.md)
|
||||||
- [Philips SAA1099](saa1099.md)
|
- [Philips SAA1099](saa1099.md)
|
||||||
- [Microchip AY8930](ay8930.md)
|
- [Microchip AY8930](ay8930.md)
|
||||||
|
|
@ -28,6 +29,7 @@ this is a list of systems that Furnace supports, including each system's effects
|
||||||
- [Yamaha OPL](opl.md)
|
- [Yamaha OPL](opl.md)
|
||||||
- [PC Speaker](pcspkr.md)
|
- [PC Speaker](pcspkr.md)
|
||||||
- [Commodore PET](pet.md)
|
- [Commodore PET](pet.md)
|
||||||
|
- [Konami SCC](scc.md)
|
||||||
- [Commodore VIC-20](vic20.md)
|
- [Commodore VIC-20](vic20.md)
|
||||||
- [Konami VRC6](vrc6.md)
|
- [Konami VRC6](vrc6.md)
|
||||||
- [Famicom Disk System](fds.md)
|
- [Famicom Disk System](fds.md)
|
||||||
|
|
|
||||||
|
|
@ -1,14 +1,12 @@
|
||||||
# Bubble System WSG
|
# Bubble System WSG
|
||||||
|
|
||||||
a Konami's 2 channel wavetable sound generator logic used at their arcade hardware Bubble System.
|
a Konami-made 2 channel wavetable sound generator logic used on the Bubble System arcade board, configured with K005289, a 4-bit PROM and DAC.
|
||||||
|
|
||||||
It's configured with K005289, 4 bit PROM and DAC.
|
however, the K005289 is just part of the logic used for pitch and wavetable ROM address.
|
||||||
|
waveform select and volume control are tied with single AY-3-8910 IO for both channels.
|
||||||
|
another AY-3-8910 IO is used for reading sound hardware status.
|
||||||
|
|
||||||
Also known as K005289, but that's just part of the logic used for pitch and wavetable ROM address.
|
Furnace emulates this configuration as single system with 32x16 wavetables.
|
||||||
Waveform select and Volume control are tied with single AY-3-8910 IO for both channels.
|
|
||||||
Another AY-3-8910 IO is used for reading sound hardware status.
|
|
||||||
|
|
||||||
Furnace emulates this configurations as single system, waveform format is 15 level and 32 width.
|
|
||||||
|
|
||||||
# effects
|
# effects
|
||||||
|
|
||||||
|
|
|
||||||
11
papers/doc/7-systems/scc.md
Normal file
11
papers/doc/7-systems/scc.md
Normal file
|
|
@ -0,0 +1,11 @@
|
||||||
|
# Konami SCC/SCC+
|
||||||
|
|
||||||
|
the Sound Creative Chip (SCC) adds 5 channels of wavetable to your MSX!
|
||||||
|
it was used in (of course) several Konami games, which had better audio quality due to the extra channels provided by this chip (poor AY since nobody used the envelope for bass).
|
||||||
|
|
||||||
|
the only problem? the waveform of the fourth channel is shared with the fifth one due to not enough memory in the chip!
|
||||||
|
the SCC+ fixes this issue though (while being compatible with SCC games).
|
||||||
|
|
||||||
|
# effects
|
||||||
|
|
||||||
|
- `10xx`: change wave.
|
||||||
|
|
@ -4,7 +4,7 @@
|
||||||
|
|
||||||
yep, that's right! 16 channels of PCM!
|
yep, that's right! 16 channels of PCM!
|
||||||
|
|
||||||
a chip used in the Sega OutRun/X/Y arcade boards. eventually the MultiPCM surpassed it with 24 channels, and later they joined the software mixing gang.
|
a chip used in the Sega OutRun/X/Y arcade boards. eventually the MultiPCM surpassed it with 28 channels, and later they joined the software mixing gang.
|
||||||
|
|
||||||
# effects
|
# effects
|
||||||
- `20xx`: set PCM frequency.
|
- `20xx`: set PCM frequency.
|
||||||
|
|
|
||||||
101
papers/doc/7-systems/ym2203.md
Normal file
101
papers/doc/7-systems/ym2203.md
Normal file
|
|
@ -0,0 +1,101 @@
|
||||||
|
# Yamaha YM2203 (OPN)
|
||||||
|
|
||||||
|
a cost-reduced version of the YM2151 (OPM).
|
||||||
|
it only has 3 FM channels instead of 8 and removes stereo, the LFO and DT2 (coarse detune).
|
||||||
|
|
||||||
|
however it does contain an AY/SSG part which provides 3 channels of square wave with noise and envelope.
|
||||||
|
|
||||||
|
this chip was used in the NEC PC-88/PC-98 series of computers, the Fujitsu FM-7AV and in some arcade boards.
|
||||||
|
|
||||||
|
several variants of this chip were released as well, with more features.
|
||||||
|
|
||||||
|
# effects
|
||||||
|
|
||||||
|
- `11xx`: set feedback of channel.
|
||||||
|
- `12xx`: set operator 1 level.
|
||||||
|
- `13xx`: set operator 2 level.
|
||||||
|
- `14xx`: set operator 3 level.
|
||||||
|
- `15xx`: set operator 4 level.
|
||||||
|
- `16xy`: set multiplier of operator.
|
||||||
|
- `x` is the operator (1-4).
|
||||||
|
- `y` is the mutliplier.
|
||||||
|
- `18xx`: toggle extended channel 3 mode.
|
||||||
|
- 0 disables it and 1 enables it.
|
||||||
|
- only in extended channel 3 system.
|
||||||
|
- `19xx`: set attack of all operators.
|
||||||
|
- `1Axx`: set attack of operator 1.
|
||||||
|
- `1Bxx`: set attack of operator 2.
|
||||||
|
- `1Cxx`: set attack of operator 3.
|
||||||
|
- `1Dxx`: set attack of operator 4.
|
||||||
|
- `20xx`: set SSG channel mode. `xx` may be one of the following:
|
||||||
|
- `00`: square
|
||||||
|
- `01`: noise
|
||||||
|
- `02`: square and noise
|
||||||
|
- `03`: nothing (apparently)
|
||||||
|
- `04`: envelope and square
|
||||||
|
- `05`: envelope and noise
|
||||||
|
- `06`: envelope and square and noise
|
||||||
|
- `07`: nothing
|
||||||
|
- `21xx`: set noise frequency. `xx` is a value between 00 and 1F.
|
||||||
|
- `22xy`: set envelope mode.
|
||||||
|
- `x` sets the envelope shape, which may be one of the following:
|
||||||
|
- `0: \___` decay
|
||||||
|
- `4: /___` attack once
|
||||||
|
- `8: \\\\` saw
|
||||||
|
- `9: \___` decay
|
||||||
|
- `A: \/\/` inverse obelisco
|
||||||
|
- `B: \¯¯¯` decay once
|
||||||
|
- `C: ////` inverse saw
|
||||||
|
- `D: /¯¯¯` attack
|
||||||
|
- `E: /\/\` obelisco
|
||||||
|
- `F: /___` attack once
|
||||||
|
- if `y` is 1 then the envelope will affect this channel.
|
||||||
|
- `23xx`: set envelope period low byte.
|
||||||
|
- `24xx`: set envelope period high byte.
|
||||||
|
- `25xx`: slide envelope period up.
|
||||||
|
- `26xx`: slide envelope period down.
|
||||||
|
- `29xy`: enable SSG auto-envelope mode.
|
||||||
|
- in this mode the envelope period is set to the channel's notes, multiplied by a fraction.
|
||||||
|
- `x` is the numerator.
|
||||||
|
- `y` is the denominator.
|
||||||
|
- if `x` or `y` are 0 this will disable auto-envelope mode.
|
||||||
|
- `30xx`: enable envelope hard reset.
|
||||||
|
- this works by inserting a quick release and tiny delay before a new note.
|
||||||
|
- `50xy`: set AM of operator.
|
||||||
|
- `x` is the operator (1-4). a value of 0 means "all operators".
|
||||||
|
- `y` determines whether AM is on.
|
||||||
|
- `51xy` set SL of operator.
|
||||||
|
- `x` is the operator (1-4). a value of 0 means "all operators".
|
||||||
|
- `y` is the value.
|
||||||
|
- `52xy` set RR of operator.
|
||||||
|
- `x` is the operator (1-4). a value of 0 means "all operators".
|
||||||
|
- `y` is the value.
|
||||||
|
- `53xy` set DT of operator.
|
||||||
|
- `x` is the operator (1-4). a value of 0 means "all operators".
|
||||||
|
- `y` is the value:
|
||||||
|
- 0: +0
|
||||||
|
- 1: +1
|
||||||
|
- 2: +2
|
||||||
|
- 3: +3
|
||||||
|
- 4: -0
|
||||||
|
- 5: -3
|
||||||
|
- 6: -2
|
||||||
|
- 7: -1
|
||||||
|
- `54xy` set RS of operator.
|
||||||
|
- `x` is the operator (1-4). a value of 0 means "all operators".
|
||||||
|
- `y` is the value.
|
||||||
|
- `55xy` set SSG-EG of operator.
|
||||||
|
- `x` is the operator (1-4). a value of 0 means "all operators".
|
||||||
|
- `y` is the value (0-8).
|
||||||
|
- values between 0 and 7 set SSG-EG.
|
||||||
|
- value 8 disables it.
|
||||||
|
- `56xx`: set DR of all operators.
|
||||||
|
- `57xx`: set DR of operator 1.
|
||||||
|
- `58xx`: set DR of operator 2.
|
||||||
|
- `59xx`: set DR of operator 3.
|
||||||
|
- `5Axx`: set DR of operator 4.
|
||||||
|
- `5Bxx`: set D2R/SR of all operators.
|
||||||
|
- `5Cxx`: set D2R/SR of operator 1.
|
||||||
|
- `5Dxx`: set D2R/SR of operator 2.
|
||||||
|
- `5Exx`: set D2R/SR of operator 3.
|
||||||
|
- `5Fxx`: set D2R/SR of operator 4.
|
||||||
101
papers/doc/7-systems/ym2608.md
Normal file
101
papers/doc/7-systems/ym2608.md
Normal file
|
|
@ -0,0 +1,101 @@
|
||||||
|
# Yamaha YM2608 (OPNA)
|
||||||
|
|
||||||
|
like YM2203, but with twice the FM channels, stereo, an ADPCM channel and built-in drums ("rhythm")!
|
||||||
|
|
||||||
|
it was one of the available sound chips for the NEC PC-88VA and PC-98 series of computers.
|
||||||
|
|
||||||
|
the YM2610 (OPNB) and YM2610B chips are very similar to this one, but the built-in drums have been replaced with 6 sample channels.
|
||||||
|
|
||||||
|
# effects
|
||||||
|
|
||||||
|
- `10xy`: set LFO parameters.
|
||||||
|
- `x` toggles the LFO.
|
||||||
|
- `y` sets its speed.
|
||||||
|
- `11xx`: set feedback of channel.
|
||||||
|
- `12xx`: set operator 1 level.
|
||||||
|
- `13xx`: set operator 2 level.
|
||||||
|
- `14xx`: set operator 3 level.
|
||||||
|
- `15xx`: set operator 4 level.
|
||||||
|
- `16xy`: set multiplier of operator.
|
||||||
|
- `x` is the operator (1-4).
|
||||||
|
- `y` is the mutliplier.
|
||||||
|
- `18xx`: toggle extended channel 3 mode.
|
||||||
|
- 0 disables it and 1 enables it.
|
||||||
|
- only in extended channel 3 system.
|
||||||
|
- `19xx`: set attack of all operators.
|
||||||
|
- `1Axx`: set attack of operator 1.
|
||||||
|
- `1Bxx`: set attack of operator 2.
|
||||||
|
- `1Cxx`: set attack of operator 3.
|
||||||
|
- `1Dxx`: set attack of operator 4.
|
||||||
|
- `20xx`: set SSG channel mode. `xx` may be one of the following:
|
||||||
|
- `00`: square
|
||||||
|
- `01`: noise
|
||||||
|
- `02`: square and noise
|
||||||
|
- `03`: nothing (apparently)
|
||||||
|
- `04`: envelope and square
|
||||||
|
- `05`: envelope and noise
|
||||||
|
- `06`: envelope and square and noise
|
||||||
|
- `07`: nothing
|
||||||
|
- `21xx`: set noise frequency. `xx` is a value between 00 and 1F.
|
||||||
|
- `22xy`: set envelope mode.
|
||||||
|
- `x` sets the envelope shape, which may be one of the following:
|
||||||
|
- `0: \___` decay
|
||||||
|
- `4: /___` attack once
|
||||||
|
- `8: \\\\` saw
|
||||||
|
- `9: \___` decay
|
||||||
|
- `A: \/\/` inverse obelisco
|
||||||
|
- `B: \¯¯¯` decay once
|
||||||
|
- `C: ////` inverse saw
|
||||||
|
- `D: /¯¯¯` attack
|
||||||
|
- `E: /\/\` obelisco
|
||||||
|
- `F: /___` attack once
|
||||||
|
- if `y` is 1 then the envelope will affect this channel.
|
||||||
|
- `23xx`: set envelope period low byte.
|
||||||
|
- `24xx`: set envelope period high byte.
|
||||||
|
- `25xx`: slide envelope period up.
|
||||||
|
- `26xx`: slide envelope period down.
|
||||||
|
- `29xy`: enable SSG auto-envelope mode.
|
||||||
|
- in this mode the envelope period is set to the channel's notes, multiplied by a fraction.
|
||||||
|
- `x` is the numerator.
|
||||||
|
- `y` is the denominator.
|
||||||
|
- if `x` or `y` are 0 this will disable auto-envelope mode.
|
||||||
|
- `30xx`: enable envelope hard reset.
|
||||||
|
- this works by inserting a quick release and tiny delay before a new note.
|
||||||
|
- `50xy`: set AM of operator.
|
||||||
|
- `x` is the operator (1-4). a value of 0 means "all operators".
|
||||||
|
- `y` determines whether AM is on.
|
||||||
|
- `51xy` set SL of operator.
|
||||||
|
- `x` is the operator (1-4). a value of 0 means "all operators".
|
||||||
|
- `y` is the value.
|
||||||
|
- `52xy` set RR of operator.
|
||||||
|
- `x` is the operator (1-4). a value of 0 means "all operators".
|
||||||
|
- `y` is the value.
|
||||||
|
- `53xy` set DT of operator.
|
||||||
|
- `x` is the operator (1-4). a value of 0 means "all operators".
|
||||||
|
- `y` is the value:
|
||||||
|
- 0: +0
|
||||||
|
- 1: +1
|
||||||
|
- 2: +2
|
||||||
|
- 3: +3
|
||||||
|
- 4: -0
|
||||||
|
- 5: -3
|
||||||
|
- 6: -2
|
||||||
|
- 7: -1
|
||||||
|
- `54xy` set RS of operator.
|
||||||
|
- `x` is the operator (1-4). a value of 0 means "all operators".
|
||||||
|
- `y` is the value.
|
||||||
|
- `55xy` set SSG-EG of operator.
|
||||||
|
- `x` is the operator (1-4). a value of 0 means "all operators".
|
||||||
|
- `y` is the value (0-8).
|
||||||
|
- values between 0 and 7 set SSG-EG.
|
||||||
|
- value 8 disables it.
|
||||||
|
- `56xx`: set DR of all operators.
|
||||||
|
- `57xx`: set DR of operator 1.
|
||||||
|
- `58xx`: set DR of operator 2.
|
||||||
|
- `59xx`: set DR of operator 3.
|
||||||
|
- `5Axx`: set DR of operator 4.
|
||||||
|
- `5Bxx`: set D2R/SR of all operators.
|
||||||
|
- `5Cxx`: set D2R/SR of operator 1.
|
||||||
|
- `5Dxx`: set D2R/SR of operator 2.
|
||||||
|
- `5Exx`: set D2R/SR of operator 3.
|
||||||
|
- `5Fxx`: set D2R/SR of operator 4.
|
||||||
|
|
@ -16,9 +16,9 @@ it is backward compatible with the original chip.
|
||||||
- `16xy`: set multiplier of operator.
|
- `16xy`: set multiplier of operator.
|
||||||
- `x` is the operator (1-4).
|
- `x` is the operator (1-4).
|
||||||
- `y` is the mutliplier.
|
- `y` is the mutliplier.
|
||||||
- `18xx`: toggle extended channel 2 mode.
|
- `18xx`: toggle extended channel 3 mode.
|
||||||
- 0 disables it and 1 enables it.
|
- 0 disables it and 1 enables it.
|
||||||
- only in extended channel 2 system.
|
- only in extended channel 3 system.
|
||||||
- `19xx`: set attack of all operators.
|
- `19xx`: set attack of all operators.
|
||||||
- `1Axx`: set attack of operator 1.
|
- `1Axx`: set attack of operator 1.
|
||||||
- `1Bxx`: set attack of operator 2.
|
- `1Bxx`: set attack of operator 2.
|
||||||
|
|
@ -95,4 +95,4 @@ it is backward compatible with the original chip.
|
||||||
- `5Cxx`: set D2R/SR of operator 1.
|
- `5Cxx`: set D2R/SR of operator 1.
|
||||||
- `5Dxx`: set D2R/SR of operator 2.
|
- `5Dxx`: set D2R/SR of operator 2.
|
||||||
- `5Exx`: set D2R/SR of operator 3.
|
- `5Exx`: set D2R/SR of operator 3.
|
||||||
- `5Fxx`: set D2R/SR of operator 4.
|
- `5Fxx`: set D2R/SR of operator 4.
|
||||||
|
|
|
||||||
|
|
@ -30,6 +30,7 @@
|
||||||
#include "platform/arcade.h"
|
#include "platform/arcade.h"
|
||||||
#include "platform/tx81z.h"
|
#include "platform/tx81z.h"
|
||||||
#include "platform/ym2203.h"
|
#include "platform/ym2203.h"
|
||||||
|
#include "platform/ym2608.h"
|
||||||
#include "platform/ym2610.h"
|
#include "platform/ym2610.h"
|
||||||
#include "platform/ym2610ext.h"
|
#include "platform/ym2610ext.h"
|
||||||
#include "platform/ym2610b.h"
|
#include "platform/ym2610b.h"
|
||||||
|
|
@ -58,6 +59,7 @@
|
||||||
#include "platform/scc.h"
|
#include "platform/scc.h"
|
||||||
#include "platform/dummy.h"
|
#include "platform/dummy.h"
|
||||||
#include "../ta-log.h"
|
#include "../ta-log.h"
|
||||||
|
#include "platform/zxbeeper.h"
|
||||||
#include "song.h"
|
#include "song.h"
|
||||||
|
|
||||||
void DivDispatchContainer::setRates(double gotRate) {
|
void DivDispatchContainer::setRates(double gotRate) {
|
||||||
|
|
@ -238,6 +240,9 @@ void DivDispatchContainer::init(DivSystem sys, DivEngine* eng, int chanCount, do
|
||||||
case DIV_SYSTEM_OPN:
|
case DIV_SYSTEM_OPN:
|
||||||
dispatch=new DivPlatformYM2203;
|
dispatch=new DivPlatformYM2203;
|
||||||
break;
|
break;
|
||||||
|
case DIV_SYSTEM_PC98:
|
||||||
|
dispatch=new DivPlatformYM2608;
|
||||||
|
break;
|
||||||
case DIV_SYSTEM_OPLL:
|
case DIV_SYSTEM_OPLL:
|
||||||
case DIV_SYSTEM_OPLL_DRUMS:
|
case DIV_SYSTEM_OPLL_DRUMS:
|
||||||
case DIV_SYSTEM_VRC7:
|
case DIV_SYSTEM_VRC7:
|
||||||
|
|
@ -269,6 +274,14 @@ void DivDispatchContainer::init(DivSystem sys, DivEngine* eng, int chanCount, do
|
||||||
dispatch=new DivPlatformOPL;
|
dispatch=new DivPlatformOPL;
|
||||||
((DivPlatformOPL*)dispatch)->setOPLType(3,true);
|
((DivPlatformOPL*)dispatch)->setOPLType(3,true);
|
||||||
break;
|
break;
|
||||||
|
case DIV_SYSTEM_Y8950:
|
||||||
|
dispatch=new DivPlatformOPL;
|
||||||
|
((DivPlatformOPL*)dispatch)->setOPLType(8950,false);
|
||||||
|
break;
|
||||||
|
case DIV_SYSTEM_Y8950_DRUMS:
|
||||||
|
dispatch=new DivPlatformOPL;
|
||||||
|
((DivPlatformOPL*)dispatch)->setOPLType(8950,true);
|
||||||
|
break;
|
||||||
case DIV_SYSTEM_OPZ:
|
case DIV_SYSTEM_OPZ:
|
||||||
dispatch=new DivPlatformTX81Z;
|
dispatch=new DivPlatformTX81Z;
|
||||||
break;
|
break;
|
||||||
|
|
@ -282,6 +295,9 @@ void DivDispatchContainer::init(DivSystem sys, DivEngine* eng, int chanCount, do
|
||||||
case DIV_SYSTEM_PCSPKR:
|
case DIV_SYSTEM_PCSPKR:
|
||||||
dispatch=new DivPlatformPCSpeaker;
|
dispatch=new DivPlatformPCSpeaker;
|
||||||
break;
|
break;
|
||||||
|
case DIV_SYSTEM_SFX_BEEPER:
|
||||||
|
dispatch=new DivPlatformZXBeeper;
|
||||||
|
break;
|
||||||
case DIV_SYSTEM_LYNX:
|
case DIV_SYSTEM_LYNX:
|
||||||
dispatch=new DivPlatformLynx;
|
dispatch=new DivPlatformLynx;
|
||||||
break;
|
break;
|
||||||
|
|
|
||||||
|
|
@ -491,6 +491,86 @@ void DivEngine::notifyWaveChange(int wave) {
|
||||||
BUSY_END;
|
BUSY_END;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
int DivEngine::loadSampleROM(String path, ssize_t expectedSize, unsigned char*& ret) {
|
||||||
|
ret = NULL;
|
||||||
|
if (path.empty()) {
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
logI("loading ROM %s...",path);
|
||||||
|
FILE* f=ps_fopen(path.c_str(),"rb");
|
||||||
|
if (f==NULL) {
|
||||||
|
logE("error: %s",strerror(errno));
|
||||||
|
lastError=strerror(errno);
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
if (fseek(f,0,SEEK_END)<0) {
|
||||||
|
logE("size error: %s",strerror(errno));
|
||||||
|
lastError=fmt::sprintf("on seek: %s",strerror(errno));
|
||||||
|
fclose(f);
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
ssize_t len=ftell(f);
|
||||||
|
if (len==(SIZE_MAX>>1)) {
|
||||||
|
logE("could not get file length: %s",strerror(errno));
|
||||||
|
lastError=fmt::sprintf("on pre tell: %s",strerror(errno));
|
||||||
|
fclose(f);
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
if (len<1) {
|
||||||
|
if (len==0) {
|
||||||
|
logE("that file is empty!");
|
||||||
|
lastError="file is empty";
|
||||||
|
} else {
|
||||||
|
logE("tell error: %s",strerror(errno));
|
||||||
|
lastError=fmt::sprintf("on tell: %s",strerror(errno));
|
||||||
|
}
|
||||||
|
fclose(f);
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
if (len!=expectedSize) {
|
||||||
|
logE("ROM size mismatch, expected: %d bytes, was: %d bytes", expectedSize, len);
|
||||||
|
lastError=fmt::sprintf("ROM size mismatch, expected: %d bytes, was: %d", expectedSize, len);
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
if (fseek(f,0,SEEK_SET)<0) {
|
||||||
|
logE("size error: %s",strerror(errno));
|
||||||
|
lastError=fmt::sprintf("on get size: %s",strerror(errno));
|
||||||
|
fclose(f);
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
unsigned char* file=new unsigned char[len];
|
||||||
|
if (fread(file,1,(size_t)len,f)!=(size_t)len) {
|
||||||
|
logE("read error: %s",strerror(errno));
|
||||||
|
lastError=fmt::sprintf("on read: %s",strerror(errno));
|
||||||
|
fclose(f);
|
||||||
|
delete[] file;
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
fclose(f);
|
||||||
|
ret = file;
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
int DivEngine::loadSampleROMs() {
|
||||||
|
if (yrw801ROM!=NULL) {
|
||||||
|
delete[] yrw801ROM;
|
||||||
|
yrw801ROM=NULL;
|
||||||
|
}
|
||||||
|
if (tg100ROM!=NULL) {
|
||||||
|
delete[] tg100ROM;
|
||||||
|
tg100ROM=NULL;
|
||||||
|
}
|
||||||
|
if (mu5ROM!=NULL) {
|
||||||
|
delete[] mu5ROM;
|
||||||
|
mu5ROM=NULL;
|
||||||
|
}
|
||||||
|
int error = 0;
|
||||||
|
error += loadSampleROM(getConfString("yrw801Path",""), 0x200000, yrw801ROM);
|
||||||
|
error += loadSampleROM(getConfString("tg100Path",""), 0x200000, tg100ROM);
|
||||||
|
error += loadSampleROM(getConfString("mu5Path",""), 0x200000, mu5ROM);
|
||||||
|
return error;
|
||||||
|
}
|
||||||
|
|
||||||
void DivEngine::renderSamplesP() {
|
void DivEngine::renderSamplesP() {
|
||||||
BUSY_BEGIN;
|
BUSY_BEGIN;
|
||||||
renderSamples();
|
renderSamples();
|
||||||
|
|
@ -1532,7 +1612,9 @@ int DivEngine::addInstrument(int refChan) {
|
||||||
*ins=song.nullInsQSound;
|
*ins=song.nullInsQSound;
|
||||||
}
|
}
|
||||||
ins->name=fmt::sprintf("Instrument %d",insCount);
|
ins->name=fmt::sprintf("Instrument %d",insCount);
|
||||||
ins->type=prefType;
|
if (prefType!=DIV_INS_NULL) {
|
||||||
|
ins->type=prefType;
|
||||||
|
}
|
||||||
saveLock.lock();
|
saveLock.lock();
|
||||||
song.ins.push_back(ins);
|
song.ins.push_back(ins);
|
||||||
song.insLen=insCount+1;
|
song.insLen=insCount+1;
|
||||||
|
|
@ -2230,9 +2312,9 @@ void DivEngine::autoNoteOn(int ch, int ins, int note, int vol) {
|
||||||
|
|
||||||
// 1. check which channels are viable for this instrument
|
// 1. check which channels are viable for this instrument
|
||||||
DivInstrument* insInst=getIns(ins);
|
DivInstrument* insInst=getIns(ins);
|
||||||
if (getPreferInsType(finalChan)!=insInst->type && getPreferInsSecondType(finalChan)!=insInst->type) notInViableChannel=true;
|
if (getPreferInsType(finalChan)!=insInst->type && getPreferInsSecondType(finalChan)!=insInst->type && getPreferInsType(finalChan)!=DIV_INS_NULL) notInViableChannel=true;
|
||||||
for (int i=0; i<chans; i++) {
|
for (int i=0; i<chans; i++) {
|
||||||
if (ins==-1 || ins>=song.insLen || getPreferInsType(i)==insInst->type || getPreferInsSecondType(i)==insInst->type) {
|
if (ins==-1 || ins>=song.insLen || getPreferInsType(i)==insInst->type || (getPreferInsType(i)==DIV_INS_NULL && finalChanType==DIV_CH_NOISE) || getPreferInsSecondType(i)==insInst->type) {
|
||||||
if (insInst->type==DIV_INS_OPL) {
|
if (insInst->type==DIV_INS_OPL) {
|
||||||
if (insInst->fm.ops==2 || getChannelType(i)==DIV_CH_OP) {
|
if (insInst->fm.ops==2 || getChannelType(i)==DIV_CH_OP) {
|
||||||
isViable[i]=true;
|
isViable[i]=true;
|
||||||
|
|
@ -2708,6 +2790,8 @@ bool DivEngine::init() {
|
||||||
|
|
||||||
loadConf();
|
loadConf();
|
||||||
|
|
||||||
|
loadSampleROMs();
|
||||||
|
|
||||||
// set default system preset
|
// set default system preset
|
||||||
if (!hasLoadedSomething) {
|
if (!hasLoadedSomething) {
|
||||||
logD("setting default preset");
|
logD("setting default preset");
|
||||||
|
|
@ -2781,5 +2865,8 @@ bool DivEngine::quit() {
|
||||||
active=false;
|
active=false;
|
||||||
delete[] oscBuf[0];
|
delete[] oscBuf[0];
|
||||||
delete[] oscBuf[1];
|
delete[] oscBuf[1];
|
||||||
|
if (yrw801ROM!=NULL) delete[] yrw801ROM;
|
||||||
|
if (tg100ROM!=NULL) delete[] tg100ROM;
|
||||||
|
if (mu5ROM!=NULL) delete[] mu5ROM;
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -188,6 +188,7 @@ typedef std::function<bool(int,unsigned char,unsigned char)> EffectProcess;
|
||||||
struct DivSysDef {
|
struct DivSysDef {
|
||||||
const char* name;
|
const char* name;
|
||||||
const char* nameJ;
|
const char* nameJ;
|
||||||
|
const char* description;
|
||||||
unsigned char id;
|
unsigned char id;
|
||||||
unsigned char id_DMF;
|
unsigned char id_DMF;
|
||||||
int channels;
|
int channels;
|
||||||
|
|
@ -203,7 +204,7 @@ struct DivSysDef {
|
||||||
EffectProcess postEffectFunc;
|
EffectProcess postEffectFunc;
|
||||||
DivSysDef(
|
DivSysDef(
|
||||||
const char* sysName, const char* sysNameJ, unsigned char fileID, unsigned char fileID_DMF, int chans,
|
const char* sysName, const char* sysNameJ, unsigned char fileID, unsigned char fileID_DMF, int chans,
|
||||||
bool isFMChip, bool isSTDChip, unsigned int vgmVer, bool compound,
|
bool isFMChip, bool isSTDChip, unsigned int vgmVer, bool compound, const char* desc,
|
||||||
std::initializer_list<const char*> chNames,
|
std::initializer_list<const char*> chNames,
|
||||||
std::initializer_list<const char*> chShortNames,
|
std::initializer_list<const char*> chShortNames,
|
||||||
std::initializer_list<int> chTypes,
|
std::initializer_list<int> chTypes,
|
||||||
|
|
@ -213,6 +214,7 @@ struct DivSysDef {
|
||||||
EffectProcess postFxHandler=[](int,unsigned char,unsigned char) -> bool {return false;}):
|
EffectProcess postFxHandler=[](int,unsigned char,unsigned char) -> bool {return false;}):
|
||||||
name(sysName),
|
name(sysName),
|
||||||
nameJ(sysNameJ),
|
nameJ(sysNameJ),
|
||||||
|
description(desc),
|
||||||
id(fileID),
|
id(fileID),
|
||||||
id_DMF(fileID_DMF),
|
id_DMF(fileID_DMF),
|
||||||
channels(chans),
|
channels(chans),
|
||||||
|
|
@ -400,6 +402,8 @@ class DivEngine {
|
||||||
void loadWOPL(SafeReader& reader, std::vector<DivInstrument*>& ret, String& stripPath);
|
void loadWOPL(SafeReader& reader, std::vector<DivInstrument*>& ret, String& stripPath);
|
||||||
void loadWOPN(SafeReader& reader, std::vector<DivInstrument*>& ret, String& stripPath);
|
void loadWOPN(SafeReader& reader, std::vector<DivInstrument*>& ret, String& stripPath);
|
||||||
|
|
||||||
|
int loadSampleROM(String path, ssize_t expectedSize, unsigned char*& ret);
|
||||||
|
|
||||||
bool initAudioBackend();
|
bool initAudioBackend();
|
||||||
bool deinitAudioBackend();
|
bool deinitAudioBackend();
|
||||||
|
|
||||||
|
|
@ -786,6 +790,9 @@ class DivEngine {
|
||||||
// get register cheatsheet
|
// get register cheatsheet
|
||||||
const char** getRegisterSheet(int sys);
|
const char** getRegisterSheet(int sys);
|
||||||
|
|
||||||
|
// load sample ROMs
|
||||||
|
int loadSampleROMs();
|
||||||
|
|
||||||
// UNSAFE render samples - only execute when locked
|
// UNSAFE render samples - only execute when locked
|
||||||
void renderSamples();
|
void renderSamples();
|
||||||
|
|
||||||
|
|
@ -859,6 +866,10 @@ class DivEngine {
|
||||||
// terminate the engine.
|
// terminate the engine.
|
||||||
bool quit();
|
bool quit();
|
||||||
|
|
||||||
|
unsigned char* yrw801ROM;
|
||||||
|
unsigned char* tg100ROM;
|
||||||
|
unsigned char* mu5ROM;
|
||||||
|
|
||||||
DivEngine():
|
DivEngine():
|
||||||
output(NULL),
|
output(NULL),
|
||||||
exportThread(NULL),
|
exportThread(NULL),
|
||||||
|
|
@ -933,7 +944,10 @@ class DivEngine {
|
||||||
oscReadPos(0),
|
oscReadPos(0),
|
||||||
oscWritePos(0),
|
oscWritePos(0),
|
||||||
tickMult(1),
|
tickMult(1),
|
||||||
processTime(0) {
|
processTime(0),
|
||||||
|
yrw801ROM(NULL),
|
||||||
|
tg100ROM(NULL),
|
||||||
|
mu5ROM(NULL) {
|
||||||
memset(isMuted,0,DIV_MAX_CHANS*sizeof(bool));
|
memset(isMuted,0,DIV_MAX_CHANS*sizeof(bool));
|
||||||
memset(keyHit,0,DIV_MAX_CHANS*sizeof(bool));
|
memset(keyHit,0,DIV_MAX_CHANS*sizeof(bool));
|
||||||
memset(dispatchChanOfChan,0,DIV_MAX_CHANS*sizeof(int));
|
memset(dispatchChanOfChan,0,DIV_MAX_CHANS*sizeof(int));
|
||||||
|
|
|
||||||
|
|
@ -654,7 +654,7 @@ bool DivEngine::loadDMF(unsigned char* file, size_t len) {
|
||||||
}
|
}
|
||||||
for (int j=0; j<ds.ordersLen; j++) {
|
for (int j=0; j<ds.ordersLen; j++) {
|
||||||
DivPattern* pat=chan.getPattern(ds.orders.ord[i][j],true);
|
DivPattern* pat=chan.getPattern(ds.orders.ord[i][j],true);
|
||||||
if (ds.version>0x05) { // current pattern format
|
if (ds.version>0x08) { // current pattern format
|
||||||
for (int k=0; k<ds.patLen; k++) {
|
for (int k=0; k<ds.patLen; k++) {
|
||||||
// note
|
// note
|
||||||
pat->data[k][0]=reader.readS();
|
pat->data[k][0]=reader.readS();
|
||||||
|
|
@ -741,11 +741,15 @@ bool DivEngine::loadDMF(unsigned char* file, size_t len) {
|
||||||
unsigned char vol=reader.readC();
|
unsigned char vol=reader.readC();
|
||||||
unsigned char fx=reader.readC();
|
unsigned char fx=reader.readC();
|
||||||
unsigned char fxVal=reader.readC();
|
unsigned char fxVal=reader.readC();
|
||||||
pat->data[k][3]=(vol==0x80)?-1:vol;
|
pat->data[k][3]=(vol==0x80 || vol==0xff)?-1:vol;
|
||||||
// effect
|
// effect
|
||||||
pat->data[k][4]=(fx==0x80)?-1:fx;
|
pat->data[k][4]=(fx==0x80 || fx==0xff)?-1:fx;
|
||||||
pat->data[k][5]=(fxVal==0x80)?-1:fxVal;
|
pat->data[k][5]=(fxVal==0x80 || fx==0xff)?-1:fxVal;
|
||||||
// instrument wasn't stored back then
|
// instrument
|
||||||
|
if (ds.version>0x05) {
|
||||||
|
pat->data[k][2]=reader.readC();
|
||||||
|
if (pat->data[k][2]==0x80 || pat->data[k][2]==0xff) pat->data[k][2]=-1;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -311,6 +311,32 @@ struct DivInstrumentAmiga {
|
||||||
int noteFreq[120];
|
int noteFreq[120];
|
||||||
short noteMap[120];
|
short noteMap[120];
|
||||||
|
|
||||||
|
/**
|
||||||
|
* get the sample at specified note.
|
||||||
|
* @return the sample.
|
||||||
|
*/
|
||||||
|
inline short getSample(int note) {
|
||||||
|
if (useNoteMap) {
|
||||||
|
if (note<0) note=0;
|
||||||
|
if (note>119) note=119;
|
||||||
|
return noteMap[note];
|
||||||
|
}
|
||||||
|
return initSample;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* get the sample frequency at specified note.
|
||||||
|
* @return the frequency, or -1 if not using note map.
|
||||||
|
*/
|
||||||
|
inline int getFreq(int note) {
|
||||||
|
if (useNoteMap) {
|
||||||
|
if (note<0) note=0;
|
||||||
|
if (note>119) note=119;
|
||||||
|
return noteFreq[note];
|
||||||
|
}
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
DivInstrumentAmiga():
|
DivInstrumentAmiga():
|
||||||
initSample(0),
|
initSample(0),
|
||||||
useNoteMap(false),
|
useNoteMap(false),
|
||||||
|
|
|
||||||
|
|
@ -220,7 +220,7 @@ void DivPlatformAmiga::tick(bool sysTick) {
|
||||||
}
|
}
|
||||||
if (chan[i].freqChanged || chan[i].keyOn || chan[i].keyOff) {
|
if (chan[i].freqChanged || chan[i].keyOn || chan[i].keyOff) {
|
||||||
//DivInstrument* ins=parent->getIns(chan[i].ins,DIV_INS_AMIGA);
|
//DivInstrument* ins=parent->getIns(chan[i].ins,DIV_INS_AMIGA);
|
||||||
chan[i].freq=parent->calcFreq(chan[i].baseFreq,chan[i].pitch,true,0,chan[i].pitch2,chipClock,CHIP_DIVIDER);
|
chan[i].freq=off*parent->calcFreq(chan[i].baseFreq,chan[i].pitch,true,0,chan[i].pitch2,chipClock,CHIP_DIVIDER);
|
||||||
if (chan[i].freq>4095) chan[i].freq=4095;
|
if (chan[i].freq>4095) chan[i].freq=4095;
|
||||||
if (chan[i].freq<0) chan[i].freq=0;
|
if (chan[i].freq<0) chan[i].freq=0;
|
||||||
if (chan[i].keyOn) {
|
if (chan[i].keyOn) {
|
||||||
|
|
@ -238,7 +238,6 @@ int DivPlatformAmiga::dispatch(DivCommand c) {
|
||||||
switch (c.cmd) {
|
switch (c.cmd) {
|
||||||
case DIV_CMD_NOTE_ON: {
|
case DIV_CMD_NOTE_ON: {
|
||||||
DivInstrument* ins=parent->getIns(chan[c.chan].ins,DIV_INS_AMIGA);
|
DivInstrument* ins=parent->getIns(chan[c.chan].ins,DIV_INS_AMIGA);
|
||||||
double off=1.0;
|
|
||||||
if (ins->amiga.useWave) {
|
if (ins->amiga.useWave) {
|
||||||
chan[c.chan].useWave=true;
|
chan[c.chan].useWave=true;
|
||||||
chan[c.chan].audLen=(ins->amiga.waveLen+1)>>1;
|
chan[c.chan].audLen=(ins->amiga.waveLen+1)>>1;
|
||||||
|
|
@ -250,19 +249,11 @@ int DivPlatformAmiga::dispatch(DivCommand c) {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
chan[c.chan].sample=ins->amiga.initSample;
|
chan[c.chan].sample=ins->amiga.getSample(c.value);
|
||||||
chan[c.chan].useWave=false;
|
chan[c.chan].useWave=false;
|
||||||
if (chan[c.chan].sample>=0 && chan[c.chan].sample<parent->song.sampleLen) {
|
|
||||||
DivSample* s=parent->getSample(chan[c.chan].sample);
|
|
||||||
if (s->centerRate<1) {
|
|
||||||
off=1.0;
|
|
||||||
} else {
|
|
||||||
off=8363.0/(double)s->centerRate;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
if (c.value!=DIV_NOTE_NULL) {
|
if (c.value!=DIV_NOTE_NULL) {
|
||||||
chan[c.chan].baseFreq=round(off*NOTE_PERIODIC_NOROUND(c.value));
|
chan[c.chan].baseFreq=round(NOTE_PERIODIC_NOROUND(c.value));
|
||||||
}
|
}
|
||||||
if (chan[c.chan].useWave || chan[c.chan].sample<0 || chan[c.chan].sample>=parent->song.sampleLen) {
|
if (chan[c.chan].useWave || chan[c.chan].sample<0 || chan[c.chan].sample>=parent->song.sampleLen) {
|
||||||
chan[c.chan].sample=-1;
|
chan[c.chan].sample=-1;
|
||||||
|
|
@ -328,17 +319,8 @@ int DivPlatformAmiga::dispatch(DivCommand c) {
|
||||||
break;
|
break;
|
||||||
case DIV_CMD_NOTE_PORTA: {
|
case DIV_CMD_NOTE_PORTA: {
|
||||||
DivInstrument* ins=parent->getIns(chan[c.chan].ins,DIV_INS_AMIGA);
|
DivInstrument* ins=parent->getIns(chan[c.chan].ins,DIV_INS_AMIGA);
|
||||||
chan[c.chan].sample=ins->amiga.initSample;
|
chan[c.chan].sample=ins->amiga.getSample(c.value2);
|
||||||
double off=1.0;
|
int destFreq=round(NOTE_PERIODIC_NOROUND(c.value2));
|
||||||
if (!chan[c.chan].useWave && chan[c.chan].sample>=0 && chan[c.chan].sample<parent->song.sampleLen) {
|
|
||||||
DivSample* s=parent->getSample(chan[c.chan].sample);
|
|
||||||
if (s->centerRate<1) {
|
|
||||||
off=1.0;
|
|
||||||
} else {
|
|
||||||
off=8363.0/(double)s->centerRate;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
int destFreq=round(off*NOTE_PERIODIC_NOROUND(c.value2));
|
|
||||||
bool return2=false;
|
bool return2=false;
|
||||||
if (destFreq>chan[c.chan].baseFreq) {
|
if (destFreq>chan[c.chan].baseFreq) {
|
||||||
chan[c.chan].baseFreq+=c.value;
|
chan[c.chan].baseFreq+=c.value;
|
||||||
|
|
@ -361,16 +343,7 @@ int DivPlatformAmiga::dispatch(DivCommand c) {
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
case DIV_CMD_LEGATO: {
|
case DIV_CMD_LEGATO: {
|
||||||
double off=1.0;
|
chan[c.chan].baseFreq=round(NOTE_PERIODIC_NOROUND(c.value+((chan[c.chan].std.arp.will && !chan[c.chan].std.arp.mode)?(chan[c.chan].std.arp.val):(0))));
|
||||||
if (!chan[c.chan].useWave && chan[c.chan].sample>=0 && chan[c.chan].sample<parent->song.sampleLen) {
|
|
||||||
DivSample* s=parent->getSample(chan[c.chan].sample);
|
|
||||||
if (s->centerRate<1) {
|
|
||||||
off=1.0;
|
|
||||||
} else {
|
|
||||||
off=8363.0/(double)s->centerRate;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
chan[c.chan].baseFreq=round(off*NOTE_PERIODIC_NOROUND(c.value+((chan[c.chan].std.arp.will && !chan[c.chan].std.arp.mode)?(chan[c.chan].std.arp.val):(0))));
|
|
||||||
chan[c.chan].freqChanged=true;
|
chan[c.chan].freqChanged=true;
|
||||||
chan[c.chan].note=c.value;
|
chan[c.chan].note=c.value;
|
||||||
break;
|
break;
|
||||||
|
|
|
||||||
|
|
@ -547,7 +547,7 @@ int DivPlatformGenesis::dispatch(DivCommand c) {
|
||||||
if (c.chan==5 && dacMode) {
|
if (c.chan==5 && dacMode) {
|
||||||
if (skipRegisterWrites) break;
|
if (skipRegisterWrites) break;
|
||||||
if (ins->type==DIV_INS_AMIGA) { // Furnace mode
|
if (ins->type==DIV_INS_AMIGA) { // Furnace mode
|
||||||
dacSample=ins->amiga.initSample;
|
dacSample=ins->amiga.getSample(c.value);
|
||||||
if (dacSample<0 || dacSample>=parent->song.sampleLen) {
|
if (dacSample<0 || dacSample>=parent->song.sampleLen) {
|
||||||
dacSample=-1;
|
dacSample=-1;
|
||||||
if (dumpWrites) addWrite(0xffff0002,0);
|
if (dumpWrites) addWrite(0xffff0002,0);
|
||||||
|
|
|
||||||
|
|
@ -192,7 +192,7 @@ int DivPlatformMMC5::dispatch(DivCommand c) {
|
||||||
if (c.chan==2) { // PCM
|
if (c.chan==2) { // PCM
|
||||||
DivInstrument* ins=parent->getIns(chan[c.chan].ins,DIV_INS_STD);
|
DivInstrument* ins=parent->getIns(chan[c.chan].ins,DIV_INS_STD);
|
||||||
if (ins->type==DIV_INS_AMIGA) {
|
if (ins->type==DIV_INS_AMIGA) {
|
||||||
dacSample=ins->amiga.initSample;
|
dacSample=ins->amiga.getSample(c.value);
|
||||||
if (dacSample<0 || dacSample>=parent->song.sampleLen) {
|
if (dacSample<0 || dacSample>=parent->song.sampleLen) {
|
||||||
dacSample=-1;
|
dacSample=-1;
|
||||||
if (dumpWrites) addWrite(0xffff0002,0);
|
if (dumpWrites) addWrite(0xffff0002,0);
|
||||||
|
|
|
||||||
|
|
@ -381,7 +381,7 @@ int DivPlatformNES::dispatch(DivCommand c) {
|
||||||
if (c.chan==4) { // PCM
|
if (c.chan==4) { // PCM
|
||||||
DivInstrument* ins=parent->getIns(chan[c.chan].ins,DIV_INS_STD);
|
DivInstrument* ins=parent->getIns(chan[c.chan].ins,DIV_INS_STD);
|
||||||
if (ins->type==DIV_INS_AMIGA) {
|
if (ins->type==DIV_INS_AMIGA) {
|
||||||
dacSample=ins->amiga.initSample;
|
dacSample=ins->amiga.getSample(c.value);
|
||||||
if (dacSample<0 || dacSample>=parent->song.sampleLen) {
|
if (dacSample<0 || dacSample>=parent->song.sampleLen) {
|
||||||
dacSample=-1;
|
dacSample=-1;
|
||||||
if (dumpWrites && !dpcmMode) addWrite(0xffff0002,0);
|
if (dumpWrites && !dpcmMode) addWrite(0xffff0002,0);
|
||||||
|
|
|
||||||
|
|
@ -19,6 +19,7 @@
|
||||||
|
|
||||||
#include "opl.h"
|
#include "opl.h"
|
||||||
#include "../engine.h"
|
#include "../engine.h"
|
||||||
|
#include "../../ta-log.h"
|
||||||
#include <string.h>
|
#include <string.h>
|
||||||
#include <math.h>
|
#include <math.h>
|
||||||
|
|
||||||
|
|
@ -246,19 +247,53 @@ const char* DivPlatformOPL::getEffectName(unsigned char effect) {
|
||||||
void DivPlatformOPL::acquire_nuked(short* bufL, short* bufR, size_t start, size_t len) {
|
void DivPlatformOPL::acquire_nuked(short* bufL, short* bufR, size_t start, size_t len) {
|
||||||
static short o[2];
|
static short o[2];
|
||||||
static int os[2];
|
static int os[2];
|
||||||
|
static ymfm::ymfm_output<2> aOut;
|
||||||
|
|
||||||
for (size_t h=start; h<start+len; h++) {
|
for (size_t h=start; h<start+len; h++) {
|
||||||
os[0]=0; os[1]=0;
|
os[0]=0; os[1]=0;
|
||||||
if (!writes.empty() && --delay<0) {
|
if (!writes.empty() && --delay<0) {
|
||||||
delay=1;
|
delay=1;
|
||||||
QueuedWrite& w=writes.front();
|
QueuedWrite& w=writes.front();
|
||||||
OPL3_WriteReg(&fm,w.addr,w.val);
|
switch (w.addr) {
|
||||||
|
case 8:
|
||||||
|
if (adpcmChan>=0) {
|
||||||
|
adpcmB->write(w.addr-7,(w.val&15)|0x80);
|
||||||
|
OPL3_WriteReg(&fm,w.addr,w.val&0xc0);
|
||||||
|
} else {
|
||||||
|
OPL3_WriteReg(&fm,w.addr,w.val);
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
case 7: case 9: case 10: case 11: case 12: case 13: case 14: case 15: case 16: case 17: case 18: case 21: case 22: case 23:
|
||||||
|
if (adpcmChan>=0) {
|
||||||
|
adpcmB->write(w.addr-7,w.val);
|
||||||
|
} else {
|
||||||
|
OPL3_WriteReg(&fm,w.addr,w.val);
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
OPL3_WriteReg(&fm,w.addr,w.val);
|
||||||
|
break;
|
||||||
|
}
|
||||||
regPool[w.addr&511]=w.val;
|
regPool[w.addr&511]=w.val;
|
||||||
writes.pop();
|
writes.pop();
|
||||||
}
|
}
|
||||||
|
|
||||||
OPL3_Generate(&fm,o); os[0]+=o[0]; os[1]+=o[1];
|
OPL3_Generate(&fm,o); os[0]+=o[0]; os[1]+=o[1];
|
||||||
|
|
||||||
|
if (adpcmChan>=0) {
|
||||||
|
adpcmB->clock();
|
||||||
|
aOut.clear();
|
||||||
|
adpcmB->output<2>(aOut,0);
|
||||||
|
|
||||||
|
if (!isMuted[adpcmChan]) {
|
||||||
|
os[0]+=aOut.data[0];
|
||||||
|
os[1]+=aOut.data[0];
|
||||||
|
oscBuf[adpcmChan]->data[oscBuf[adpcmChan]->needle++]+=aOut.data[0];
|
||||||
|
} else {
|
||||||
|
oscBuf[adpcmChan]->data[oscBuf[adpcmChan]->needle++]=0;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
for (int i=0; i<chans; i++) {
|
for (int i=0; i<chans; i++) {
|
||||||
unsigned char ch=outChanMap[i];
|
unsigned char ch=outChanMap[i];
|
||||||
if (ch==255) continue;
|
if (ch==255) continue;
|
||||||
|
|
@ -292,6 +327,15 @@ void DivPlatformOPL::acquire(short* bufL, short* bufR, size_t start, size_t len)
|
||||||
//}
|
//}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
double DivPlatformOPL::NOTE_ADPCMB(int note) {
|
||||||
|
if (adpcmChan<0) return 0;
|
||||||
|
if (chan[adpcmChan].sample>=0 && chan[adpcmChan].sample<parent->song.sampleLen) {
|
||||||
|
double off=65535.0*(double)(parent->getSample(chan[adpcmChan].sample)->centerRate)/8363.0;
|
||||||
|
return parent->calcBaseFreq((double)chipClock/144,off,note,false);
|
||||||
|
}
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
void DivPlatformOPL::tick(bool sysTick) {
|
void DivPlatformOPL::tick(bool sysTick) {
|
||||||
for (int i=0; i<totalChans; i++) {
|
for (int i=0; i<totalChans; i++) {
|
||||||
int ops=(slots[3][i]!=255 && chan[i].state.ops==4 && oplType==3)?4:2;
|
int ops=(slots[3][i]!=255 && chan[i].state.ops==4 && oplType==3)?4:2;
|
||||||
|
|
@ -501,6 +545,45 @@ void DivPlatformOPL::tick(bool sysTick) {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// ADPCM
|
||||||
|
if (adpcmChan>=0) {
|
||||||
|
if (chan[adpcmChan].furnacePCM) {
|
||||||
|
chan[adpcmChan].std.next();
|
||||||
|
|
||||||
|
if (chan[adpcmChan].std.vol.had) {
|
||||||
|
chan[adpcmChan].outVol=(chan[adpcmChan].vol*MIN(64,chan[adpcmChan].std.vol.val))/64;
|
||||||
|
immWrite(18,chan[adpcmChan].outVol);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (chan[adpcmChan].std.arp.had) {
|
||||||
|
if (!chan[adpcmChan].inPorta) {
|
||||||
|
if (chan[adpcmChan].std.arp.mode) {
|
||||||
|
chan[adpcmChan].baseFreq=NOTE_ADPCMB(chan[adpcmChan].std.arp.val);
|
||||||
|
} else {
|
||||||
|
chan[adpcmChan].baseFreq=NOTE_ADPCMB(chan[adpcmChan].note+(signed char)chan[adpcmChan].std.arp.val);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
chan[adpcmChan].freqChanged=true;
|
||||||
|
} else {
|
||||||
|
if (chan[adpcmChan].std.arp.mode && chan[adpcmChan].std.arp.finished) {
|
||||||
|
chan[adpcmChan].baseFreq=NOTE_ADPCMB(chan[adpcmChan].note);
|
||||||
|
chan[adpcmChan].freqChanged=true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (chan[adpcmChan].freqChanged) {
|
||||||
|
if (chan[adpcmChan].sample>=0 && chan[adpcmChan].sample<parent->song.sampleLen) {
|
||||||
|
double off=65535.0*(double)(parent->getSample(chan[adpcmChan].sample)->centerRate)/8363.0;
|
||||||
|
chan[adpcmChan].freq=parent->calcFreq(chan[adpcmChan].baseFreq,chan[adpcmChan].pitch,false,4,chan[adpcmChan].pitch2,(double)chipClock/144,off);
|
||||||
|
} else {
|
||||||
|
chan[adpcmChan].freq=0;
|
||||||
|
}
|
||||||
|
immWrite(16,chan[adpcmChan].freq&0xff);
|
||||||
|
immWrite(17,(chan[adpcmChan].freq>>8)&0xff);
|
||||||
|
chan[adpcmChan].freqChanged=false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
for (int i=0; i<512; i++) {
|
for (int i=0; i<512; i++) {
|
||||||
if (pendingWrites[i]!=oldWrites[i]) {
|
if (pendingWrites[i]!=oldWrites[i]) {
|
||||||
immWrite(i,pendingWrites[i]&0xff);
|
immWrite(i,pendingWrites[i]&0xff);
|
||||||
|
|
@ -588,6 +671,7 @@ int DivPlatformOPL::toFreq(int freq) {
|
||||||
|
|
||||||
void DivPlatformOPL::muteChannel(int ch, bool mute) {
|
void DivPlatformOPL::muteChannel(int ch, bool mute) {
|
||||||
isMuted[ch]=mute;
|
isMuted[ch]=mute;
|
||||||
|
if (ch==adpcmChan) return;
|
||||||
if (oplType<3 && ch<melodicChans) {
|
if (oplType<3 && ch<melodicChans) {
|
||||||
fm.channel[outChanMap[ch]].muted=mute;
|
fm.channel[outChanMap[ch]].muted=mute;
|
||||||
}
|
}
|
||||||
|
|
@ -625,13 +709,78 @@ void DivPlatformOPL::muteChannel(int ch, bool mute) {
|
||||||
}
|
}
|
||||||
|
|
||||||
int DivPlatformOPL::dispatch(DivCommand c) {
|
int DivPlatformOPL::dispatch(DivCommand c) {
|
||||||
if (c.chan>=totalChans) return 0;
|
if (c.chan>=totalChans && c.chan!=adpcmChan) return 0;
|
||||||
// ineffective in 4-op mode
|
// ineffective in 4-op mode
|
||||||
if (oplType==3 && c.chan<14 && (c.chan&1) && c.cmd!=DIV_CMD_GET_VOLMAX && c.cmd!=DIV_ALWAYS_SET_VOLUME) {
|
if (oplType==3 && c.chan!=adpcmChan && c.chan<14 && (c.chan&1) && c.cmd!=DIV_CMD_GET_VOLMAX && c.cmd!=DIV_ALWAYS_SET_VOLUME) {
|
||||||
if (chan[c.chan-1].fourOp) return 0;
|
if (chan[c.chan-1].fourOp) return 0;
|
||||||
}
|
}
|
||||||
switch (c.cmd) {
|
switch (c.cmd) {
|
||||||
case DIV_CMD_NOTE_ON: {
|
case DIV_CMD_NOTE_ON: {
|
||||||
|
if (c.chan==adpcmChan) { // ADPCM
|
||||||
|
DivInstrument* ins=parent->getIns(chan[c.chan].ins,DIV_INS_FM);
|
||||||
|
if (ins->type==DIV_INS_AMIGA) {
|
||||||
|
chan[c.chan].furnacePCM=true;
|
||||||
|
} else {
|
||||||
|
chan[c.chan].furnacePCM=false;
|
||||||
|
}
|
||||||
|
if (skipRegisterWrites) break;
|
||||||
|
if (chan[c.chan].furnacePCM) {
|
||||||
|
chan[c.chan].macroInit(ins);
|
||||||
|
if (!chan[c.chan].std.vol.will) {
|
||||||
|
chan[c.chan].outVol=chan[c.chan].vol;
|
||||||
|
immWrite(18,chan[c.chan].outVol);
|
||||||
|
}
|
||||||
|
chan[c.chan].sample=ins->amiga.getSample(c.value);
|
||||||
|
if (chan[c.chan].sample>=0 && chan[c.chan].sample<parent->song.sampleLen) {
|
||||||
|
DivSample* s=parent->getSample(chan[c.chan].sample);
|
||||||
|
immWrite(9,(s->offB>>2)&0xff);
|
||||||
|
immWrite(10,(s->offB>>10)&0xff);
|
||||||
|
int end=s->offB+s->lengthB-1;
|
||||||
|
immWrite(11,(end>>2)&0xff);
|
||||||
|
immWrite(12,(end>>10)&0xff);
|
||||||
|
immWrite(8,2);
|
||||||
|
immWrite(7,(s->loopStart>=0)?0xb0:0xa0); // start/repeat
|
||||||
|
if (c.value!=DIV_NOTE_NULL) {
|
||||||
|
chan[c.chan].note=c.value;
|
||||||
|
chan[c.chan].baseFreq=NOTE_ADPCMB(chan[c.chan].note);
|
||||||
|
chan[c.chan].freqChanged=true;
|
||||||
|
}
|
||||||
|
chan[c.chan].active=true;
|
||||||
|
chan[c.chan].keyOn=true;
|
||||||
|
} else {
|
||||||
|
immWrite(7,0x01); // reset
|
||||||
|
immWrite(9,0);
|
||||||
|
immWrite(10,0);
|
||||||
|
immWrite(11,0);
|
||||||
|
immWrite(12,0);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
chan[c.chan].sample=-1;
|
||||||
|
chan[c.chan].macroInit(NULL);
|
||||||
|
chan[c.chan].outVol=chan[c.chan].vol;
|
||||||
|
if ((12*sampleBank+c.value%12)>=parent->song.sampleLen) {
|
||||||
|
immWrite(7,0x01); // reset
|
||||||
|
immWrite(9,0);
|
||||||
|
immWrite(10,0);
|
||||||
|
immWrite(11,0);
|
||||||
|
immWrite(12,0);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
DivSample* s=parent->getSample(12*sampleBank+c.value%12);
|
||||||
|
immWrite(9,(s->offB>>2)&0xff);
|
||||||
|
immWrite(10,(s->offB>>10)&0xff);
|
||||||
|
int end=s->offB+s->lengthB-1;
|
||||||
|
immWrite(11,(end>>2)&0xff);
|
||||||
|
immWrite(12,(end>>10)&0xff);
|
||||||
|
immWrite(8,2);
|
||||||
|
immWrite(7,(s->loopStart>=0)?0xb0:0xa0); // start/repeat
|
||||||
|
int freq=(65536.0*(double)s->rate)/(double)rate;
|
||||||
|
immWrite(16,freq&0xff);
|
||||||
|
immWrite(17,(freq>>8)&0xff);
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
}
|
||||||
DivInstrument* ins=parent->getIns(chan[c.chan].ins,DIV_INS_OPL);
|
DivInstrument* ins=parent->getIns(chan[c.chan].ins,DIV_INS_OPL);
|
||||||
|
|
||||||
if (chan[c.chan].insChanged) {
|
if (chan[c.chan].insChanged) {
|
||||||
|
|
@ -714,11 +863,19 @@ int DivPlatformOPL::dispatch(DivCommand c) {
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
case DIV_CMD_NOTE_OFF:
|
case DIV_CMD_NOTE_OFF:
|
||||||
|
if (c.chan==adpcmChan) {
|
||||||
|
immWrite(7,0x01); // reset
|
||||||
|
break;
|
||||||
|
}
|
||||||
chan[c.chan].keyOff=true;
|
chan[c.chan].keyOff=true;
|
||||||
chan[c.chan].keyOn=false;
|
chan[c.chan].keyOn=false;
|
||||||
chan[c.chan].active=false;
|
chan[c.chan].active=false;
|
||||||
break;
|
break;
|
||||||
case DIV_CMD_NOTE_OFF_ENV:
|
case DIV_CMD_NOTE_OFF_ENV:
|
||||||
|
if (c.chan==adpcmChan) {
|
||||||
|
immWrite(7,0x01); // reset
|
||||||
|
break;
|
||||||
|
}
|
||||||
chan[c.chan].keyOff=true;
|
chan[c.chan].keyOff=true;
|
||||||
chan[c.chan].keyOn=false;
|
chan[c.chan].keyOn=false;
|
||||||
chan[c.chan].active=false;
|
chan[c.chan].active=false;
|
||||||
|
|
@ -728,7 +885,7 @@ int DivPlatformOPL::dispatch(DivCommand c) {
|
||||||
chan[c.chan].std.release();
|
chan[c.chan].std.release();
|
||||||
break;
|
break;
|
||||||
case DIV_CMD_VOLUME: {
|
case DIV_CMD_VOLUME: {
|
||||||
if (pretendYMU) {
|
if (pretendYMU && c.chan!=adpcmChan) {
|
||||||
c.value=pow(((double)c.value/127.0),0.5)*63.0;
|
c.value=pow(((double)c.value/127.0),0.5)*63.0;
|
||||||
if (c.value<0) c.value=0;
|
if (c.value<0) c.value=0;
|
||||||
if (c.value>63) c.value=63;
|
if (c.value>63) c.value=63;
|
||||||
|
|
@ -737,6 +894,10 @@ int DivPlatformOPL::dispatch(DivCommand c) {
|
||||||
if (!chan[c.chan].std.vol.has) {
|
if (!chan[c.chan].std.vol.has) {
|
||||||
chan[c.chan].outVol=c.value;
|
chan[c.chan].outVol=c.value;
|
||||||
}
|
}
|
||||||
|
if (c.chan==adpcmChan) { // ADPCM-B
|
||||||
|
immWrite(18,chan[c.chan].outVol);
|
||||||
|
break;
|
||||||
|
}
|
||||||
int ops=(slots[3][c.chan]!=255 && chan[c.chan].state.ops==4 && oplType==3)?4:2;
|
int ops=(slots[3][c.chan]!=255 && chan[c.chan].state.ops==4 && oplType==3)?4:2;
|
||||||
for (int i=0; i<ops; i++) {
|
for (int i=0; i<ops; i++) {
|
||||||
unsigned char slot=slots[i][c.chan];
|
unsigned char slot=slots[i][c.chan];
|
||||||
|
|
@ -757,7 +918,7 @@ int DivPlatformOPL::dispatch(DivCommand c) {
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
case DIV_CMD_GET_VOLUME: {
|
case DIV_CMD_GET_VOLUME: {
|
||||||
if (pretendYMU) {
|
if (pretendYMU && c.chan!=adpcmChan) {
|
||||||
return pow(((double)chan[c.chan].vol/63.0),2.0)*127.0;
|
return pow(((double)chan[c.chan].vol/63.0),2.0)*127.0;
|
||||||
}
|
}
|
||||||
return chan[c.chan].vol;
|
return chan[c.chan].vol;
|
||||||
|
|
@ -771,6 +932,7 @@ int DivPlatformOPL::dispatch(DivCommand c) {
|
||||||
break;
|
break;
|
||||||
case DIV_CMD_PANNING: {
|
case DIV_CMD_PANNING: {
|
||||||
if (oplType!=3) break;
|
if (oplType!=3) break;
|
||||||
|
if (c.chan==adpcmChan) break;
|
||||||
if (c.value==0 && c.value2==0) {
|
if (c.value==0 && c.value2==0) {
|
||||||
chan[c.chan].pan=3;
|
chan[c.chan].pan=3;
|
||||||
} else {
|
} else {
|
||||||
|
|
@ -791,12 +953,15 @@ int DivPlatformOPL::dispatch(DivCommand c) {
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
case DIV_CMD_PITCH: {
|
case DIV_CMD_PITCH: {
|
||||||
|
if (c.chan==adpcmChan) {
|
||||||
|
if (!chan[c.chan].furnacePCM) break;
|
||||||
|
}
|
||||||
chan[c.chan].pitch=c.value;
|
chan[c.chan].pitch=c.value;
|
||||||
chan[c.chan].freqChanged=true;
|
chan[c.chan].freqChanged=true;
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
case DIV_CMD_NOTE_PORTA: {
|
case DIV_CMD_NOTE_PORTA: {
|
||||||
int destFreq=NOTE_FREQUENCY(c.value2);
|
int destFreq=(c.chan==adpcmChan)?(NOTE_ADPCMB(c.value2)):(NOTE_FREQUENCY(c.value2));
|
||||||
int newFreq;
|
int newFreq;
|
||||||
bool return2=false;
|
bool return2=false;
|
||||||
if (destFreq>chan[c.chan].baseFreq) {
|
if (destFreq>chan[c.chan].baseFreq) {
|
||||||
|
|
@ -827,13 +992,22 @@ int DivPlatformOPL::dispatch(DivCommand c) {
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
case DIV_CMD_SAMPLE_BANK:
|
||||||
|
if (adpcmChan<0) break;
|
||||||
|
sampleBank=c.value;
|
||||||
|
if (sampleBank>(int)(parent->song.sample.size()/12)) {
|
||||||
|
sampleBank=parent->song.sample.size()/12;
|
||||||
|
}
|
||||||
|
iface.sampleBank=sampleBank;
|
||||||
|
break;
|
||||||
case DIV_CMD_LEGATO: {
|
case DIV_CMD_LEGATO: {
|
||||||
chan[c.chan].baseFreq=NOTE_FREQUENCY(c.value);
|
chan[c.chan].baseFreq=(c.chan==adpcmChan)?(NOTE_ADPCMB(c.value)):(NOTE_FREQUENCY(c.value));
|
||||||
chan[c.chan].note=c.value;
|
chan[c.chan].note=c.value;
|
||||||
chan[c.chan].freqChanged=true;
|
chan[c.chan].freqChanged=true;
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
case DIV_CMD_FM_LFO: {
|
case DIV_CMD_FM_LFO: {
|
||||||
|
if (c.chan==adpcmChan) break;
|
||||||
if (c.value&2) {
|
if (c.value&2) {
|
||||||
dvb=c.value&1;
|
dvb=c.value&1;
|
||||||
} else {
|
} else {
|
||||||
|
|
@ -843,6 +1017,7 @@ int DivPlatformOPL::dispatch(DivCommand c) {
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
case DIV_CMD_FM_FB: {
|
case DIV_CMD_FM_FB: {
|
||||||
|
if (c.chan==adpcmChan) break;
|
||||||
chan[c.chan].state.fb=c.value&7;
|
chan[c.chan].state.fb=c.value&7;
|
||||||
int ops=(slots[3][c.chan]!=255 && chan[c.chan].state.ops==4 && oplType==3)?4:2;
|
int ops=(slots[3][c.chan]!=255 && chan[c.chan].state.ops==4 && oplType==3)?4:2;
|
||||||
if (isMuted[c.chan]) {
|
if (isMuted[c.chan]) {
|
||||||
|
|
@ -859,6 +1034,7 @@ int DivPlatformOPL::dispatch(DivCommand c) {
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
case DIV_CMD_FM_MULT: {
|
case DIV_CMD_FM_MULT: {
|
||||||
|
if (c.chan==adpcmChan) break;
|
||||||
int ops=(slots[3][c.chan]!=255 && chan[c.chan].state.ops==4 && oplType==3)?4:2;
|
int ops=(slots[3][c.chan]!=255 && chan[c.chan].state.ops==4 && oplType==3)?4:2;
|
||||||
if (c.value>=ops) break;
|
if (c.value>=ops) break;
|
||||||
DivInstrumentFM::Operator& op=chan[c.chan].state.op[(ops==4)?orderedOpsL[c.value]:c.value];
|
DivInstrumentFM::Operator& op=chan[c.chan].state.op[(ops==4)?orderedOpsL[c.value]:c.value];
|
||||||
|
|
@ -870,6 +1046,7 @@ int DivPlatformOPL::dispatch(DivCommand c) {
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
case DIV_CMD_FM_TL: {
|
case DIV_CMD_FM_TL: {
|
||||||
|
if (c.chan==adpcmChan) break;
|
||||||
int ops=(slots[3][c.chan]!=255 && chan[c.chan].state.ops==4 && oplType==3)?4:2;
|
int ops=(slots[3][c.chan]!=255 && chan[c.chan].state.ops==4 && oplType==3)?4:2;
|
||||||
if (c.value>=ops) break;
|
if (c.value>=ops) break;
|
||||||
DivInstrumentFM::Operator& op=chan[c.chan].state.op[(ops==4)?orderedOpsL[c.value]:c.value];
|
DivInstrumentFM::Operator& op=chan[c.chan].state.op[(ops==4)?orderedOpsL[c.value]:c.value];
|
||||||
|
|
@ -889,6 +1066,7 @@ int DivPlatformOPL::dispatch(DivCommand c) {
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
case DIV_CMD_FM_AR: {
|
case DIV_CMD_FM_AR: {
|
||||||
|
if (c.chan==adpcmChan) break;
|
||||||
int ops=(slots[3][c.chan]!=255 && chan[c.chan].state.ops==4 && oplType==3)?4:2;
|
int ops=(slots[3][c.chan]!=255 && chan[c.chan].state.ops==4 && oplType==3)?4:2;
|
||||||
if (c.value<0) {
|
if (c.value<0) {
|
||||||
for (int i=0; i<ops; i++) {
|
for (int i=0; i<ops; i++) {
|
||||||
|
|
@ -911,6 +1089,7 @@ int DivPlatformOPL::dispatch(DivCommand c) {
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
case DIV_CMD_FM_DR: {
|
case DIV_CMD_FM_DR: {
|
||||||
|
if (c.chan==adpcmChan) break;
|
||||||
int ops=(slots[3][c.chan]!=255 && chan[c.chan].state.ops==4 && oplType==3)?4:2;
|
int ops=(slots[3][c.chan]!=255 && chan[c.chan].state.ops==4 && oplType==3)?4:2;
|
||||||
if (c.value<0) {
|
if (c.value<0) {
|
||||||
for (int i=0; i<ops; i++) {
|
for (int i=0; i<ops; i++) {
|
||||||
|
|
@ -933,6 +1112,7 @@ int DivPlatformOPL::dispatch(DivCommand c) {
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
case DIV_CMD_FM_SL: {
|
case DIV_CMD_FM_SL: {
|
||||||
|
if (c.chan==adpcmChan) break;
|
||||||
int ops=(slots[3][c.chan]!=255 && chan[c.chan].state.ops==4 && oplType==3)?4:2;
|
int ops=(slots[3][c.chan]!=255 && chan[c.chan].state.ops==4 && oplType==3)?4:2;
|
||||||
if (c.value<0) {
|
if (c.value<0) {
|
||||||
for (int i=0; i<ops; i++) {
|
for (int i=0; i<ops; i++) {
|
||||||
|
|
@ -955,6 +1135,7 @@ int DivPlatformOPL::dispatch(DivCommand c) {
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
case DIV_CMD_FM_RR: {
|
case DIV_CMD_FM_RR: {
|
||||||
|
if (c.chan==adpcmChan) break;
|
||||||
int ops=(slots[3][c.chan]!=255 && chan[c.chan].state.ops==4 && oplType==3)?4:2;
|
int ops=(slots[3][c.chan]!=255 && chan[c.chan].state.ops==4 && oplType==3)?4:2;
|
||||||
if (c.value<0) {
|
if (c.value<0) {
|
||||||
for (int i=0; i<ops; i++) {
|
for (int i=0; i<ops; i++) {
|
||||||
|
|
@ -977,6 +1158,7 @@ int DivPlatformOPL::dispatch(DivCommand c) {
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
case DIV_CMD_FM_AM: {
|
case DIV_CMD_FM_AM: {
|
||||||
|
if (c.chan==adpcmChan) break;
|
||||||
int ops=(slots[3][c.chan]!=255 && chan[c.chan].state.ops==4 && oplType==3)?4:2;
|
int ops=(slots[3][c.chan]!=255 && chan[c.chan].state.ops==4 && oplType==3)?4:2;
|
||||||
if (c.value<0) {
|
if (c.value<0) {
|
||||||
for (int i=0; i<ops; i++) {
|
for (int i=0; i<ops; i++) {
|
||||||
|
|
@ -999,6 +1181,7 @@ int DivPlatformOPL::dispatch(DivCommand c) {
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
case DIV_CMD_FM_VIB: {
|
case DIV_CMD_FM_VIB: {
|
||||||
|
if (c.chan==adpcmChan) break;
|
||||||
int ops=(slots[3][c.chan]!=255 && chan[c.chan].state.ops==4 && oplType==3)?4:2;
|
int ops=(slots[3][c.chan]!=255 && chan[c.chan].state.ops==4 && oplType==3)?4:2;
|
||||||
if (c.value<0) {
|
if (c.value<0) {
|
||||||
for (int i=0; i<ops; i++) {
|
for (int i=0; i<ops; i++) {
|
||||||
|
|
@ -1021,6 +1204,7 @@ int DivPlatformOPL::dispatch(DivCommand c) {
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
case DIV_CMD_FM_SUS: {
|
case DIV_CMD_FM_SUS: {
|
||||||
|
if (c.chan==adpcmChan) break;
|
||||||
int ops=(slots[3][c.chan]!=255 && chan[c.chan].state.ops==4 && oplType==3)?4:2;
|
int ops=(slots[3][c.chan]!=255 && chan[c.chan].state.ops==4 && oplType==3)?4:2;
|
||||||
if (c.value<0) {
|
if (c.value<0) {
|
||||||
for (int i=0; i<ops; i++) {
|
for (int i=0; i<ops; i++) {
|
||||||
|
|
@ -1043,6 +1227,7 @@ int DivPlatformOPL::dispatch(DivCommand c) {
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
case DIV_CMD_FM_KSR: {
|
case DIV_CMD_FM_KSR: {
|
||||||
|
if (c.chan==adpcmChan) break;
|
||||||
int ops=(slots[3][c.chan]!=255 && chan[c.chan].state.ops==4 && oplType==3)?4:2;
|
int ops=(slots[3][c.chan]!=255 && chan[c.chan].state.ops==4 && oplType==3)?4:2;
|
||||||
if (c.value<0) {
|
if (c.value<0) {
|
||||||
for (int i=0; i<ops; i++) {
|
for (int i=0; i<ops; i++) {
|
||||||
|
|
@ -1065,6 +1250,7 @@ int DivPlatformOPL::dispatch(DivCommand c) {
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
case DIV_CMD_FM_WS: {
|
case DIV_CMD_FM_WS: {
|
||||||
|
if (c.chan==adpcmChan) break;
|
||||||
if (oplType<2) break;
|
if (oplType<2) break;
|
||||||
int ops=(slots[3][c.chan]!=255 && chan[c.chan].state.ops==4 && oplType==3)?4:2;
|
int ops=(slots[3][c.chan]!=255 && chan[c.chan].state.ops==4 && oplType==3)?4:2;
|
||||||
if (c.value<0) {
|
if (c.value<0) {
|
||||||
|
|
@ -1088,6 +1274,7 @@ int DivPlatformOPL::dispatch(DivCommand c) {
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
case DIV_CMD_FM_RS: {
|
case DIV_CMD_FM_RS: {
|
||||||
|
if (c.chan==adpcmChan) break;
|
||||||
if (oplType<2) break;
|
if (oplType<2) break;
|
||||||
int ops=(slots[3][c.chan]!=255 && chan[c.chan].state.ops==4 && oplType==3)?4:2;
|
int ops=(slots[3][c.chan]!=255 && chan[c.chan].state.ops==4 && oplType==3)?4:2;
|
||||||
if (c.value<0) {
|
if (c.value<0) {
|
||||||
|
|
@ -1143,12 +1330,14 @@ int DivPlatformOPL::dispatch(DivCommand c) {
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
case DIV_CMD_FM_HARD_RESET:
|
case DIV_CMD_FM_HARD_RESET:
|
||||||
|
if (c.chan==adpcmChan) break;
|
||||||
chan[c.chan].hardReset=c.value;
|
chan[c.chan].hardReset=c.value;
|
||||||
break;
|
break;
|
||||||
case DIV_ALWAYS_SET_VOLUME:
|
case DIV_ALWAYS_SET_VOLUME:
|
||||||
return 0;
|
return 0;
|
||||||
break;
|
break;
|
||||||
case DIV_CMD_GET_VOLMAX:
|
case DIV_CMD_GET_VOLMAX:
|
||||||
|
if (c.chan==adpcmChan) return 255;
|
||||||
if (pretendYMU) return 127;
|
if (pretendYMU) return 127;
|
||||||
return 63;
|
return 63;
|
||||||
break;
|
break;
|
||||||
|
|
@ -1237,7 +1426,7 @@ unsigned char* DivPlatformOPL::getRegisterPool() {
|
||||||
}
|
}
|
||||||
|
|
||||||
int DivPlatformOPL::getRegisterPoolSize() {
|
int DivPlatformOPL::getRegisterPoolSize() {
|
||||||
return 512;
|
return (oplType<3)?256:512;
|
||||||
}
|
}
|
||||||
|
|
||||||
void DivPlatformOPL::reset() {
|
void DivPlatformOPL::reset() {
|
||||||
|
|
@ -1272,6 +1461,21 @@ void DivPlatformOPL::reset() {
|
||||||
chan[i].vol=0x3f;
|
chan[i].vol=0x3f;
|
||||||
chan[i].outVol=0x3f;
|
chan[i].outVol=0x3f;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (adpcmChan>=0) {
|
||||||
|
chan[adpcmChan]=DivPlatformOPL::Channel();
|
||||||
|
chan[adpcmChan].std.setEngine(parent);
|
||||||
|
chan[adpcmChan].vol=0xff;
|
||||||
|
chan[adpcmChan].outVol=0xff;
|
||||||
|
|
||||||
|
adpcmB->reset();
|
||||||
|
|
||||||
|
// volume
|
||||||
|
immWrite(18,0xff);
|
||||||
|
// ADPCM limit
|
||||||
|
immWrite(20,0xff);
|
||||||
|
immWrite(19,0xff);
|
||||||
|
}
|
||||||
|
|
||||||
if (oplType<3) for (int i=0; i<melodicChans; i++) {
|
if (oplType<3) for (int i=0; i<melodicChans; i++) {
|
||||||
fm.channel[outChanMap[i]].muted=isMuted[i];
|
fm.channel[outChanMap[i]].muted=isMuted[i];
|
||||||
|
|
@ -1285,6 +1489,7 @@ void DivPlatformOPL::reset() {
|
||||||
lastBusy=60;
|
lastBusy=60;
|
||||||
lfoValue=8;
|
lfoValue=8;
|
||||||
drumState=0;
|
drumState=0;
|
||||||
|
sampleBank=0;
|
||||||
|
|
||||||
drumVol[0]=0;
|
drumVol[0]=0;
|
||||||
drumVol[1]=0;
|
drumVol[1]=0;
|
||||||
|
|
@ -1349,8 +1554,9 @@ void DivPlatformOPL::setYMFM(bool use) {
|
||||||
|
|
||||||
void DivPlatformOPL::setOPLType(int type, bool drums) {
|
void DivPlatformOPL::setOPLType(int type, bool drums) {
|
||||||
pretendYMU=false;
|
pretendYMU=false;
|
||||||
|
adpcmChan=-1;
|
||||||
switch (type) {
|
switch (type) {
|
||||||
case 1: case 2:
|
case 1: case 2: case 8950:
|
||||||
slotsNonDrums=slotsOPL2;
|
slotsNonDrums=slotsOPL2;
|
||||||
slotsDrums=slotsOPL2Drums;
|
slotsDrums=slotsOPL2Drums;
|
||||||
slots=drums?slotsDrums:slotsNonDrums;
|
slots=drums?slotsDrums:slotsNonDrums;
|
||||||
|
|
@ -1360,6 +1566,9 @@ void DivPlatformOPL::setOPLType(int type, bool drums) {
|
||||||
chans=9;
|
chans=9;
|
||||||
melodicChans=drums?6:9;
|
melodicChans=drums?6:9;
|
||||||
totalChans=drums?11:9;
|
totalChans=drums?11:9;
|
||||||
|
if (type==8950) {
|
||||||
|
adpcmChan=drums?11:9;
|
||||||
|
}
|
||||||
break;
|
break;
|
||||||
case 3: case 759:
|
case 3: case 759:
|
||||||
slotsNonDrums=slotsOPL3;
|
slotsNonDrums=slotsOPL3;
|
||||||
|
|
@ -1371,11 +1580,16 @@ void DivPlatformOPL::setOPLType(int type, bool drums) {
|
||||||
chans=18;
|
chans=18;
|
||||||
melodicChans=drums?15:18;
|
melodicChans=drums?15:18;
|
||||||
totalChans=drums?20:18;
|
totalChans=drums?20:18;
|
||||||
if (type==759) pretendYMU=true;
|
if (type==759) {
|
||||||
|
pretendYMU=true;
|
||||||
|
adpcmChan=16;
|
||||||
|
}
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
if (type==759) {
|
if (type==759) {
|
||||||
oplType=3;
|
oplType=3;
|
||||||
|
} else if (type==8950) {
|
||||||
|
oplType=1;
|
||||||
} else {
|
} else {
|
||||||
oplType=type;
|
oplType=type;
|
||||||
}
|
}
|
||||||
|
|
@ -1425,6 +1639,45 @@ void DivPlatformOPL::setFlags(unsigned int flags) {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
const void* DivPlatformOPL::getSampleMem(int index) {
|
||||||
|
return (index==0 && adpcmChan>=0) ? adpcmBMem : NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
size_t DivPlatformOPL::getSampleMemCapacity(int index) {
|
||||||
|
return (index==0 && adpcmChan>=0) ? 262144 : 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
size_t DivPlatformOPL::getSampleMemUsage(int index) {
|
||||||
|
return (index==0 && adpcmChan>=0) ? adpcmBMemLen : 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
void DivPlatformOPL::renderSamples() {
|
||||||
|
if (adpcmChan<0) return;
|
||||||
|
memset(adpcmBMem,0,getSampleMemCapacity(0));
|
||||||
|
|
||||||
|
size_t memPos=0;
|
||||||
|
for (int i=0; i<parent->song.sampleLen; i++) {
|
||||||
|
DivSample* s=parent->song.sample[i];
|
||||||
|
int paddedLen=(s->lengthB+255)&(~0xff);
|
||||||
|
if ((memPos&0xf00000)!=((memPos+paddedLen)&0xf00000)) {
|
||||||
|
memPos=(memPos+0xfffff)&0xf00000;
|
||||||
|
}
|
||||||
|
if (memPos>=getSampleMemCapacity(0)) {
|
||||||
|
logW("out of ADPCM memory for sample %d!",i);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
if (memPos+paddedLen>=getSampleMemCapacity(0)) {
|
||||||
|
memcpy(adpcmBMem+memPos,s->dataB,getSampleMemCapacity(0)-memPos);
|
||||||
|
logW("out of ADPCM memory for sample %d!",i);
|
||||||
|
} else {
|
||||||
|
memcpy(adpcmBMem+memPos,s->dataB,paddedLen);
|
||||||
|
}
|
||||||
|
s->offB=memPos;
|
||||||
|
memPos+=paddedLen;
|
||||||
|
}
|
||||||
|
adpcmBMemLen=memPos+256;
|
||||||
|
}
|
||||||
|
|
||||||
int DivPlatformOPL::init(DivEngine* p, int channels, int sugRate, unsigned int flags) {
|
int DivPlatformOPL::init(DivEngine* p, int channels, int sugRate, unsigned int flags) {
|
||||||
parent=p;
|
parent=p;
|
||||||
dumpWrites=false;
|
dumpWrites=false;
|
||||||
|
|
@ -1437,6 +1690,14 @@ int DivPlatformOPL::init(DivEngine* p, int channels, int sugRate, unsigned int f
|
||||||
}
|
}
|
||||||
setFlags(flags);
|
setFlags(flags);
|
||||||
|
|
||||||
|
if (adpcmChan>=0) {
|
||||||
|
adpcmBMem=new unsigned char[getSampleMemCapacity(0)];
|
||||||
|
adpcmBMemLen=0;
|
||||||
|
iface.adpcmBMem=adpcmBMem;
|
||||||
|
iface.sampleBank=0;
|
||||||
|
adpcmB=new ymfm::adpcm_b_engine(iface,2);
|
||||||
|
}
|
||||||
|
|
||||||
reset();
|
reset();
|
||||||
return totalChans;
|
return totalChans;
|
||||||
}
|
}
|
||||||
|
|
@ -1445,6 +1706,10 @@ void DivPlatformOPL::quit() {
|
||||||
for (int i=0; i<18; i++) {
|
for (int i=0; i<18; i++) {
|
||||||
delete oscBuf[i];
|
delete oscBuf[i];
|
||||||
}
|
}
|
||||||
|
if (adpcmChan>=0) {
|
||||||
|
delete adpcmB;
|
||||||
|
delete[] adpcmBMem;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
DivPlatformOPL::~DivPlatformOPL() {
|
DivPlatformOPL::~DivPlatformOPL() {
|
||||||
|
|
|
||||||
|
|
@ -23,6 +23,16 @@
|
||||||
#include "../macroInt.h"
|
#include "../macroInt.h"
|
||||||
#include <queue>
|
#include <queue>
|
||||||
#include "../../../extern/opl/opl3.h"
|
#include "../../../extern/opl/opl3.h"
|
||||||
|
#include "sound/ymfm/ymfm_adpcm.h"
|
||||||
|
|
||||||
|
class DivOPLAInterface: public ymfm::ymfm_interface {
|
||||||
|
public:
|
||||||
|
unsigned char* adpcmBMem;
|
||||||
|
int sampleBank;
|
||||||
|
uint8_t ymfm_external_read(ymfm::access_class type, uint32_t address);
|
||||||
|
void ymfm_external_write(ymfm::access_class type, uint32_t address, uint8_t data);
|
||||||
|
DivOPLAInterface(): adpcmBMem(NULL), sampleBank(0) {}
|
||||||
|
};
|
||||||
|
|
||||||
class DivPlatformOPL: public DivDispatch {
|
class DivPlatformOPL: public DivDispatch {
|
||||||
protected:
|
protected:
|
||||||
|
|
@ -30,8 +40,8 @@ class DivPlatformOPL: public DivDispatch {
|
||||||
DivInstrumentFM state;
|
DivInstrumentFM state;
|
||||||
DivMacroInt std;
|
DivMacroInt std;
|
||||||
unsigned char freqH, freqL;
|
unsigned char freqH, freqL;
|
||||||
int freq, baseFreq, pitch, pitch2, note, ins;
|
int freq, baseFreq, pitch, pitch2, note, ins, sample;
|
||||||
bool active, insChanged, freqChanged, keyOn, keyOff, portaPause, furnaceDac, inPorta, fourOp, hardReset;
|
bool active, insChanged, freqChanged, keyOn, keyOff, portaPause, furnacePCM, inPorta, fourOp, hardReset;
|
||||||
int vol, outVol;
|
int vol, outVol;
|
||||||
unsigned char pan;
|
unsigned char pan;
|
||||||
void macroInit(DivInstrument* which) {
|
void macroInit(DivInstrument* which) {
|
||||||
|
|
@ -47,13 +57,14 @@ class DivPlatformOPL: public DivDispatch {
|
||||||
pitch2(0),
|
pitch2(0),
|
||||||
note(0),
|
note(0),
|
||||||
ins(-1),
|
ins(-1),
|
||||||
|
sample(-1),
|
||||||
active(false),
|
active(false),
|
||||||
insChanged(true),
|
insChanged(true),
|
||||||
freqChanged(false),
|
freqChanged(false),
|
||||||
keyOn(false),
|
keyOn(false),
|
||||||
keyOff(false),
|
keyOff(false),
|
||||||
portaPause(false),
|
portaPause(false),
|
||||||
furnaceDac(false),
|
furnacePCM(false),
|
||||||
inPorta(false),
|
inPorta(false),
|
||||||
fourOp(false),
|
fourOp(false),
|
||||||
hardReset(false),
|
hardReset(false),
|
||||||
|
|
@ -73,13 +84,18 @@ class DivPlatformOPL: public DivDispatch {
|
||||||
};
|
};
|
||||||
std::queue<QueuedWrite> writes;
|
std::queue<QueuedWrite> writes;
|
||||||
opl3_chip fm;
|
opl3_chip fm;
|
||||||
|
unsigned char* adpcmBMem;
|
||||||
|
size_t adpcmBMemLen;
|
||||||
|
DivOPLAInterface iface;
|
||||||
|
|
||||||
|
ymfm::adpcm_b_engine* adpcmB;
|
||||||
const unsigned char** slotsNonDrums;
|
const unsigned char** slotsNonDrums;
|
||||||
const unsigned char** slotsDrums;
|
const unsigned char** slotsDrums;
|
||||||
const unsigned char** slots;
|
const unsigned char** slots;
|
||||||
const unsigned short* chanMap;
|
const unsigned short* chanMap;
|
||||||
const unsigned char* outChanMap;
|
const unsigned char* outChanMap;
|
||||||
double chipFreqBase;
|
double chipFreqBase;
|
||||||
int delay, oplType, chans, melodicChans, totalChans;
|
int delay, oplType, chans, melodicChans, totalChans, adpcmChan, sampleBank;
|
||||||
unsigned char lastBusy;
|
unsigned char lastBusy;
|
||||||
unsigned char drumState;
|
unsigned char drumState;
|
||||||
unsigned char drumVol[5];
|
unsigned char drumVol[5];
|
||||||
|
|
@ -97,6 +113,7 @@ class DivPlatformOPL: public DivDispatch {
|
||||||
|
|
||||||
int octave(int freq);
|
int octave(int freq);
|
||||||
int toFreq(int freq);
|
int toFreq(int freq);
|
||||||
|
double NOTE_ADPCMB(int note);
|
||||||
|
|
||||||
friend void putDispatchChan(void*,int,int);
|
friend void putDispatchChan(void*,int,int);
|
||||||
|
|
||||||
|
|
@ -127,6 +144,10 @@ class DivPlatformOPL: public DivDispatch {
|
||||||
void poke(unsigned int addr, unsigned short val);
|
void poke(unsigned int addr, unsigned short val);
|
||||||
void poke(std::vector<DivRegWrite>& wlist);
|
void poke(std::vector<DivRegWrite>& wlist);
|
||||||
const char* getEffectName(unsigned char effect);
|
const char* getEffectName(unsigned char effect);
|
||||||
|
const void* getSampleMem(int index);
|
||||||
|
size_t getSampleMemCapacity(int index);
|
||||||
|
size_t getSampleMemUsage(int index);
|
||||||
|
void renderSamples();
|
||||||
int init(DivEngine* parent, int channels, int sugRate, unsigned int flags);
|
int init(DivEngine* parent, int channels, int sugRate, unsigned int flags);
|
||||||
void quit();
|
void quit();
|
||||||
~DivPlatformOPL();
|
~DivPlatformOPL();
|
||||||
|
|
|
||||||
38
src/engine/platform/oplAInterface.cpp
Normal file
38
src/engine/platform/oplAInterface.cpp
Normal file
|
|
@ -0,0 +1,38 @@
|
||||||
|
/**
|
||||||
|
* Furnace Tracker - multi-system chiptune tracker
|
||||||
|
* Copyright (C) 2021-2022 tildearrow and contributors
|
||||||
|
*
|
||||||
|
* This program is free software; you can redistribute it and/or modify
|
||||||
|
* it under the terms of the GNU General Public License as published by
|
||||||
|
* the Free Software Foundation; either version 2 of the License, or
|
||||||
|
* (at your option) any later version.
|
||||||
|
*
|
||||||
|
* This program is distributed in the hope that it will be useful,
|
||||||
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
|
* GNU General Public License for more details.
|
||||||
|
*
|
||||||
|
* You should have received a copy of the GNU General Public License along
|
||||||
|
* with this program; if not, write to the Free Software Foundation, Inc.,
|
||||||
|
* 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include "sound/ymfm/ymfm.h"
|
||||||
|
#include "opl.h"
|
||||||
|
#include "../engine.h"
|
||||||
|
|
||||||
|
uint8_t DivOPLAInterface::ymfm_external_read(ymfm::access_class type, uint32_t address) {
|
||||||
|
switch (type) {
|
||||||
|
case ymfm::ACCESS_ADPCM_B:
|
||||||
|
if (adpcmBMem==NULL) {
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
return adpcmBMem[address&0xffffff];
|
||||||
|
default:
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
void DivOPLAInterface::ymfm_external_write(ymfm::access_class type, uint32_t address, uint8_t data) {
|
||||||
|
}
|
||||||
|
|
@ -270,7 +270,7 @@ int DivPlatformPCE::dispatch(DivCommand c) {
|
||||||
if (chan[c.chan].pcm) {
|
if (chan[c.chan].pcm) {
|
||||||
if (skipRegisterWrites) break;
|
if (skipRegisterWrites) break;
|
||||||
if (ins->type==DIV_INS_AMIGA) {
|
if (ins->type==DIV_INS_AMIGA) {
|
||||||
chan[c.chan].dacSample=ins->amiga.initSample;
|
chan[c.chan].dacSample=ins->amiga.getSample(c.value);
|
||||||
if (chan[c.chan].dacSample<0 || chan[c.chan].dacSample>=parent->song.sampleLen) {
|
if (chan[c.chan].dacSample<0 || chan[c.chan].dacSample>=parent->song.sampleLen) {
|
||||||
chan[c.chan].dacSample=-1;
|
chan[c.chan].dacSample=-1;
|
||||||
if (dumpWrites) addWrite(0xffff0002+(c.chan<<8),0);
|
if (dumpWrites) addWrite(0xffff0002+(c.chan<<8),0);
|
||||||
|
|
|
||||||
|
|
@ -390,7 +390,7 @@ int DivPlatformQSound::dispatch(DivCommand c) {
|
||||||
switch (c.cmd) {
|
switch (c.cmd) {
|
||||||
case DIV_CMD_NOTE_ON: {
|
case DIV_CMD_NOTE_ON: {
|
||||||
DivInstrument* ins=parent->getIns(chan[c.chan].ins,DIV_INS_AMIGA);
|
DivInstrument* ins=parent->getIns(chan[c.chan].ins,DIV_INS_AMIGA);
|
||||||
chan[c.chan].sample=ins->amiga.initSample;
|
chan[c.chan].sample=ins->amiga.getSample(c.value);
|
||||||
if (c.value!=DIV_NOTE_NULL) {
|
if (c.value!=DIV_NOTE_NULL) {
|
||||||
chan[c.chan].baseFreq=QS_NOTE_FREQUENCY(c.value);
|
chan[c.chan].baseFreq=QS_NOTE_FREQUENCY(c.value);
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -105,6 +105,11 @@ void DivPlatformSCC::acquire(short* bufL, short* bufR, size_t start, size_t len)
|
||||||
|
|
||||||
void DivPlatformSCC::updateWave(int ch) {
|
void DivPlatformSCC::updateWave(int ch) {
|
||||||
int dstCh=(!isPlus && ch>=4)?3:ch;
|
int dstCh=(!isPlus && ch>=4)?3:ch;
|
||||||
|
if (ch==3) {
|
||||||
|
lastUpdated34=3;
|
||||||
|
} else if (ch==4) {
|
||||||
|
lastUpdated34=4;
|
||||||
|
}
|
||||||
for (int i=0; i<32; i++) {
|
for (int i=0; i<32; i++) {
|
||||||
rWrite(dstCh*32+i,(unsigned char)chan[ch].ws.output[i]-128);
|
rWrite(dstCh*32+i,(unsigned char)chan[ch].ws.output[i]-128);
|
||||||
}
|
}
|
||||||
|
|
@ -281,10 +286,15 @@ void DivPlatformSCC::forceIns() {
|
||||||
for (int i=0; i<5; i++) {
|
for (int i=0; i<5; i++) {
|
||||||
chan[i].insChanged=true;
|
chan[i].insChanged=true;
|
||||||
chan[i].freqChanged=true;
|
chan[i].freqChanged=true;
|
||||||
if (chan[i].active) {
|
if (isPlus || i<3) {
|
||||||
updateWave(i);
|
updateWave(i);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
if (!isPlus) {
|
||||||
|
if (lastUpdated34>=3) {
|
||||||
|
updateWave(lastUpdated34);
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void* DivPlatformSCC::getChanState(int ch) {
|
void* DivPlatformSCC::getChanState(int ch) {
|
||||||
|
|
@ -318,6 +328,7 @@ void DivPlatformSCC::reset() {
|
||||||
if (dumpWrites) {
|
if (dumpWrites) {
|
||||||
addWrite(0xffffffff,0);
|
addWrite(0xffffffff,0);
|
||||||
}
|
}
|
||||||
|
lastUpdated34=0;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool DivPlatformSCC::isStereo() {
|
bool DivPlatformSCC::isStereo() {
|
||||||
|
|
|
||||||
|
|
@ -57,6 +57,7 @@ class DivPlatformSCC: public DivDispatch {
|
||||||
DivDispatchOscBuffer* oscBuf[5];
|
DivDispatchOscBuffer* oscBuf[5];
|
||||||
bool isMuted[5];
|
bool isMuted[5];
|
||||||
unsigned char writeOscBuf;
|
unsigned char writeOscBuf;
|
||||||
|
int lastUpdated34;
|
||||||
|
|
||||||
scc_core* scc;
|
scc_core* scc;
|
||||||
bool isPlus;
|
bool isPlus;
|
||||||
|
|
|
||||||
|
|
@ -162,7 +162,7 @@ int DivPlatformSegaPCM::dispatch(DivCommand c) {
|
||||||
DivInstrument* ins=parent->getIns(chan[c.chan].ins,DIV_INS_AMIGA);
|
DivInstrument* ins=parent->getIns(chan[c.chan].ins,DIV_INS_AMIGA);
|
||||||
if (skipRegisterWrites) break;
|
if (skipRegisterWrites) break;
|
||||||
if (ins->type==DIV_INS_AMIGA) {
|
if (ins->type==DIV_INS_AMIGA) {
|
||||||
chan[c.chan].pcm.sample=ins->amiga.initSample;
|
chan[c.chan].pcm.sample=ins->amiga.getSample(c.value);
|
||||||
if (chan[c.chan].pcm.sample<0 || chan[c.chan].pcm.sample>=parent->song.sampleLen) {
|
if (chan[c.chan].pcm.sample<0 || chan[c.chan].pcm.sample>=parent->song.sampleLen) {
|
||||||
chan[c.chan].pcm.sample=-1;
|
chan[c.chan].pcm.sample=-1;
|
||||||
if (dumpWrites) {
|
if (dumpWrites) {
|
||||||
|
|
|
||||||
543
src/engine/platform/sound/rss.h
Normal file
543
src/engine/platform/sound/rss.h
Normal file
|
|
@ -0,0 +1,543 @@
|
||||||
|
/*
|
||||||
|
This data is derived from the chip's output - internal ROM can't be read.
|
||||||
|
It was verified, using real YM2608, that this ADPCM stream produces 100% correct output signal.
|
||||||
|
*/
|
||||||
|
|
||||||
|
const unsigned char YM2608_ADPCM_ROM[0x2000] = {
|
||||||
|
|
||||||
|
/* Source: 01BD.ROM */
|
||||||
|
/* Length: 448 / 0x000001C0 */
|
||||||
|
|
||||||
|
0x88,0x08,0x08,0x08,0x00,0x88,0x16,0x76,0x99,0xB8,0x22,0x3A,0x84,0x3C,0xB1,0x54,
|
||||||
|
0x10,0xA9,0x98,0x32,0x80,0x33,0x9A,0xA7,0x4A,0xB4,0x58,0xBC,0x15,0x29,0x8A,0x97,
|
||||||
|
0x9B,0x44,0xAC,0x80,0x12,0xDE,0x13,0x1B,0xC0,0x58,0xC8,0x11,0x0A,0xA2,0x1A,0xA0,
|
||||||
|
0x00,0x98,0x0B,0x93,0x9E,0x92,0x0A,0x88,0xBE,0x14,0x1B,0x98,0x08,0xA1,0x4A,0xC1,
|
||||||
|
0x30,0xD9,0x33,0x98,0x10,0x89,0x17,0x1A,0x82,0x29,0x37,0x0C,0x83,0x50,0x9A,0x24,
|
||||||
|
0x1A,0x83,0x10,0x23,0x19,0xB3,0x72,0x8A,0x16,0x10,0x0A,0x93,0x70,0x99,0x23,0x99,
|
||||||
|
0x02,0x20,0x91,0x18,0x02,0x41,0xAB,0x24,0x18,0x81,0x99,0x4A,0xE8,0x28,0x9A,0x99,
|
||||||
|
0xA1,0x2F,0xA8,0x9D,0x90,0x08,0xCC,0xA3,0x1D,0xCA,0x82,0x0B,0xD8,0x08,0xB9,0x09,
|
||||||
|
0xBC,0xB8,0x00,0xBE,0x90,0x1B,0xCA,0x00,0x9B,0x8A,0xA8,0x91,0x0F,0xB3,0x3D,0xB8,
|
||||||
|
0x31,0x0B,0xA5,0x0A,0x11,0xA1,0x48,0x92,0x10,0x50,0x91,0x30,0x23,0x09,0x37,0x39,
|
||||||
|
0xA2,0x72,0x89,0x92,0x30,0x83,0x1C,0x96,0x28,0xB9,0x24,0x8C,0xA1,0x31,0xAD,0xA9,
|
||||||
|
0x13,0x9C,0xBA,0xA8,0x0B,0xBF,0xB8,0x9B,0xCA,0x88,0xDB,0xB8,0x19,0xFC,0x92,0x0A,
|
||||||
|
0xBA,0x89,0xAB,0xB8,0xAB,0xD8,0x08,0xAD,0xBA,0x33,0x9D,0xAA,0x83,0x3A,0xC0,0x40,
|
||||||
|
0xB9,0x15,0x39,0xA2,0x52,0x89,0x02,0x63,0x88,0x13,0x23,0x03,0x52,0x02,0x54,0x00,
|
||||||
|
0x11,0x23,0x23,0x35,0x20,0x01,0x44,0x41,0x80,0x24,0x40,0xA9,0x45,0x19,0x81,0x12,
|
||||||
|
0x81,0x02,0x11,0x21,0x19,0x02,0x61,0x8A,0x13,0x3A,0x10,0x12,0x23,0x8B,0x37,0x18,
|
||||||
|
0x91,0x24,0x10,0x81,0x34,0x20,0x05,0x32,0x82,0x53,0x20,0x14,0x33,0x31,0x34,0x52,
|
||||||
|
0x00,0x43,0x32,0x13,0x52,0x22,0x13,0x52,0x11,0x43,0x11,0x32,0x32,0x32,0x22,0x02,
|
||||||
|
0x13,0x12,0x89,0x22,0x19,0x81,0x81,0x08,0xA8,0x08,0x8B,0x90,0x1B,0xBA,0x8A,0x9B,
|
||||||
|
0xB9,0x89,0xCA,0xB9,0xAB,0xCA,0x9B,0xCA,0xB9,0xAB,0xDA,0x99,0xAC,0xBB,0x9B,0xAC,
|
||||||
|
0xAA,0xBA,0xAC,0xAB,0x9A,0xAA,0xAA,0xBA,0xB8,0xA9,0xBA,0x99,0xA9,0x9A,0xA0,0x8A,
|
||||||
|
0xA9,0x08,0x8A,0xA9,0x00,0x99,0x89,0x88,0x98,0x08,0x99,0x00,0x89,0x80,0x08,0x98,
|
||||||
|
0x00,0x88,0x88,0x80,0x90,0x80,0x90,0x80,0x81,0x99,0x08,0x88,0x99,0x09,0x00,0x1A,
|
||||||
|
0xA8,0x10,0x9A,0x88,0x08,0x0A,0x8A,0x89,0x99,0xA8,0x98,0xA9,0x99,0x99,0xA9,0x99,
|
||||||
|
0xAA,0x8A,0xAA,0x9B,0x8A,0x9A,0xA9,0x9A,0xBA,0x99,0x9A,0xAA,0x99,0x89,0xA9,0x99,
|
||||||
|
0x98,0x9A,0x98,0x88,0x09,0x89,0x09,0x08,0x08,0x09,0x18,0x18,0x00,0x12,0x00,0x11,
|
||||||
|
0x11,0x11,0x12,0x12,0x21,0x21,0x22,0x22,0x22,0x22,0x22,0x22,0x32,0x31,0x32,0x31,
|
||||||
|
0x32,0x32,0x21,0x31,0x21,0x32,0x21,0x12,0x00,0x80,0x80,0x80,0x80,0x80,0x80,0x80,
|
||||||
|
|
||||||
|
/* Source: 02SD.ROM */
|
||||||
|
/* Length: 640 / 0x00000280 */
|
||||||
|
|
||||||
|
0x0A,0xDC,0x14,0x0B,0xBA,0xBC,0x01,0x0F,0xF5,0x2F,0x87,0x19,0xC9,0x24,0x1B,0xA1,
|
||||||
|
0x31,0x99,0x90,0x32,0x32,0xFE,0x83,0x48,0xA8,0xA9,0x23,0x19,0xBC,0x91,0x02,0x41,
|
||||||
|
0xDE,0x81,0x28,0xA8,0x0A,0xB1,0x72,0xDA,0x23,0xBC,0x04,0x19,0xB8,0x21,0x8A,0x03,
|
||||||
|
0x29,0xBA,0x14,0x21,0x0B,0xC0,0x43,0x08,0x91,0x50,0x93,0x0F,0x86,0x1A,0x91,0x18,
|
||||||
|
0x21,0xCB,0x27,0x0A,0xA1,0x42,0x8C,0xA9,0x21,0x10,0x08,0xAB,0x94,0x2A,0xDA,0x02,
|
||||||
|
0x8B,0x91,0x09,0x98,0xAE,0x80,0xA9,0x02,0x0A,0xE9,0x21,0xBB,0x15,0x20,0xBE,0x92,
|
||||||
|
0x42,0x09,0xA9,0x11,0x34,0x08,0x12,0x0A,0x27,0x29,0xA1,0x52,0x12,0x8E,0x92,0x28,
|
||||||
|
0x92,0x2B,0xD1,0x23,0xBF,0x81,0x10,0x99,0xA8,0x0A,0xC4,0x3B,0xB9,0xB0,0x00,0x62,
|
||||||
|
0xCF,0x92,0x29,0x92,0x2B,0xB1,0x1C,0xB2,0x72,0xAA,0x88,0x11,0x18,0x80,0x13,0x9E,
|
||||||
|
0x03,0x18,0xB0,0x60,0xA1,0x28,0x88,0x08,0x04,0x10,0x8F,0x96,0x19,0x90,0x01,0x09,
|
||||||
|
0xC8,0x50,0x91,0x8A,0x01,0xAB,0x03,0x50,0xBA,0x9D,0x93,0x68,0xBA,0x80,0x22,0xCB,
|
||||||
|
0x41,0xBC,0x92,0x60,0xB9,0x1A,0x95,0x4A,0xC8,0x20,0x88,0x33,0xAC,0x92,0x38,0x83,
|
||||||
|
0x09,0x80,0x16,0x09,0x29,0xD0,0x54,0x8C,0xA2,0x28,0x91,0x89,0x93,0x60,0xCD,0x85,
|
||||||
|
0x1B,0xA1,0x49,0x90,0x8A,0x80,0x34,0x0C,0xC9,0x14,0x19,0x98,0xA0,0x40,0xA9,0x21,
|
||||||
|
0xD9,0x34,0x0A,0xA9,0x10,0x23,0xCB,0x25,0xAA,0x25,0x9B,0x13,0xCD,0x16,0x09,0xA0,
|
||||||
|
0x80,0x01,0x19,0x90,0x88,0x21,0xAC,0x33,0x8B,0xD8,0x27,0x3B,0xB8,0x81,0x31,0x80,
|
||||||
|
0xAF,0x97,0x0A,0x82,0x0A,0xA0,0x21,0x89,0x8A,0xA2,0x32,0x8D,0xBB,0x87,0x19,0x21,
|
||||||
|
0xC9,0xBC,0x45,0x09,0x90,0x09,0xA1,0x24,0x1A,0xD0,0x10,0x08,0x11,0xA9,0x21,0xE8,
|
||||||
|
0x60,0xA9,0x14,0x0C,0xD1,0x32,0xAB,0x04,0x0C,0x81,0x90,0x29,0x83,0x9B,0x01,0x8F,
|
||||||
|
0x97,0x0B,0x82,0x18,0x88,0xBA,0x06,0x39,0xC8,0x23,0xBC,0x04,0x09,0x92,0x08,0x1A,
|
||||||
|
0xBB,0x74,0x8C,0x81,0x18,0x81,0x9D,0x83,0x41,0xCD,0x81,0x40,0x9A,0x90,0x10,0x12,
|
||||||
|
0x9C,0xA1,0x68,0xD8,0x33,0x9C,0x91,0x01,0x12,0xBE,0x02,0x09,0x12,0x99,0x9A,0x36,
|
||||||
|
0x0A,0xB0,0x30,0x88,0xA3,0x2D,0x12,0xBC,0x03,0x3A,0x11,0xBD,0x08,0xC8,0x62,0x80,
|
||||||
|
0x8B,0xD8,0x23,0x38,0xF9,0x12,0x08,0x99,0x91,0x21,0x99,0x85,0x2F,0xB2,0x30,0x90,
|
||||||
|
0x88,0xD9,0x53,0xAC,0x82,0x19,0x91,0x20,0xCC,0x96,0x29,0xC9,0x24,0x89,0x80,0x99,
|
||||||
|
0x12,0x08,0x18,0x88,0x99,0x23,0xAB,0x73,0xCB,0x33,0x9F,0x04,0x2B,0xB1,0x08,0x03,
|
||||||
|
0x1B,0xC9,0x21,0x32,0xFA,0x33,0xDB,0x02,0x33,0xAE,0xB9,0x54,0x8B,0xA1,0x20,0x89,
|
||||||
|
0x90,0x11,0x88,0x09,0x98,0x23,0xBE,0x37,0x8D,0x81,0x20,0xAA,0x34,0xBB,0x13,0x18,
|
||||||
|
0xB9,0x40,0xB1,0x18,0x83,0x8E,0xB2,0x72,0xBC,0x82,0x30,0xA9,0x9A,0x24,0x8B,0x27,
|
||||||
|
0x0E,0x91,0x20,0x90,0x08,0xB0,0x32,0xB9,0x21,0xB0,0xAC,0x45,0x9A,0xA1,0x50,0xA9,
|
||||||
|
0x80,0x0A,0x26,0x9B,0x11,0xBB,0x23,0x71,0xCB,0x12,0x10,0xB8,0x40,0xA9,0xA5,0x39,
|
||||||
|
0xC0,0x30,0xB2,0x20,0xAA,0xBA,0x76,0x1C,0xC1,0x48,0x98,0x80,0x18,0x81,0xAA,0x23,
|
||||||
|
0x9C,0xA2,0x32,0xAC,0x9A,0x43,0x9C,0x12,0xAD,0x82,0x72,0xBC,0x00,0x82,0x39,0xD1,
|
||||||
|
0x3A,0xB8,0x35,0x9B,0x10,0x40,0xF9,0x22,0x0A,0xC0,0x51,0xB9,0x82,0x18,0x98,0xA3,
|
||||||
|
0x79,0xD0,0x20,0x88,0x09,0x01,0x99,0x82,0x11,0x38,0xFC,0x33,0x09,0xC8,0x40,0xA9,
|
||||||
|
0x11,0x29,0xAA,0x94,0x3A,0xC2,0x4A,0xC0,0x89,0x52,0xBC,0x11,0x08,0x09,0xB8,0x71,
|
||||||
|
0xA9,0x08,0xA8,0x62,0x8D,0x92,0x10,0x00,0x9E,0x94,0x38,0xBA,0x13,0x88,0x90,0x4A,
|
||||||
|
0xE2,0x30,0xBA,0x02,0x00,0x19,0xD9,0x62,0xBB,0x04,0x0B,0xA3,0x68,0xB9,0x21,0x88,
|
||||||
|
0x9D,0x04,0x10,0x8C,0xC8,0x62,0x99,0xAA,0x24,0x1A,0x80,0x9A,0x14,0x9B,0x26,0x8C,
|
||||||
|
0x92,0x30,0xB9,0x09,0xA3,0x71,0xBB,0x10,0x19,0x82,0x39,0xDB,0x02,0x44,0x9F,0x10,
|
||||||
|
|
||||||
|
/* Source: 04TOP.ROM */
|
||||||
|
/* Length: 5952 / 0x00001740 */
|
||||||
|
|
||||||
|
0x07,0xFF,0x7C,0x3C,0x31,0xC6,0xC4,0xBB,0x7F,0x7F,0x7B,0x82,0x8A,0x4D,0x5F,0x7C,
|
||||||
|
0x3E,0x44,0xD2,0xB3,0xA0,0x19,0x1B,0x6C,0x81,0x28,0xC4,0xA1,0x1C,0x4B,0x18,0x00,
|
||||||
|
0x2A,0xA2,0x0A,0x7C,0x2A,0x00,0x01,0x89,0x98,0x48,0x8A,0x3C,0x28,0x2A,0x5B,0x3E,
|
||||||
|
0x3A,0x1A,0x3B,0x3D,0x4B,0x3B,0x4A,0x08,0x2A,0x1A,0x2C,0x4A,0x3B,0x82,0x99,0x3C,
|
||||||
|
0x5D,0x29,0x2B,0x39,0x0B,0x23,0xAB,0x1A,0x4C,0x79,0xA3,0x01,0xC1,0x2A,0x0A,0x38,
|
||||||
|
0xA7,0xB9,0x12,0x1F,0x29,0x08,0x82,0xA1,0x08,0xA9,0x42,0xAA,0x95,0xB3,0x90,0x81,
|
||||||
|
0x09,0xD4,0x1A,0x80,0x1B,0x07,0xB8,0x12,0x8E,0x49,0x81,0x92,0xD3,0x90,0xA1,0x2A,
|
||||||
|
0x02,0xE1,0xA3,0x99,0x02,0xB3,0x94,0xB3,0xB0,0xF4,0x98,0x93,0x90,0x13,0xE1,0x81,
|
||||||
|
0x99,0x38,0x91,0xA6,0xD3,0x99,0x94,0xC1,0x83,0xB1,0x92,0x98,0x49,0xC4,0xB2,0xA4,
|
||||||
|
0xA3,0xD0,0x1A,0x30,0xBA,0x59,0x02,0xD4,0xA0,0xA4,0xA2,0x8A,0x01,0x00,0xB7,0xA8,
|
||||||
|
0x18,0x2A,0x2B,0x1E,0x23,0xC8,0x1A,0x00,0x39,0xA0,0x18,0x92,0x4F,0x2D,0x5A,0x10,
|
||||||
|
0x89,0x81,0x2A,0x8B,0x6A,0x02,0x09,0xB3,0x8D,0x48,0x1B,0x80,0x19,0x34,0xF8,0x29,
|
||||||
|
0x0A,0x7B,0x2A,0x28,0x81,0x0C,0x02,0x1E,0x29,0x09,0x12,0xC2,0x94,0xE1,0x18,0x98,
|
||||||
|
0x02,0xC4,0x89,0x91,0x1A,0x20,0xA9,0x02,0x1B,0x48,0x8E,0x20,0x88,0x2D,0x08,0x59,
|
||||||
|
0x1B,0x02,0xA3,0xB1,0x8A,0x1E,0x58,0x80,0xC2,0xB6,0x88,0x91,0x88,0x11,0xA1,0xA3,
|
||||||
|
0xE2,0x01,0xB0,0x19,0x11,0x09,0xF4,0x88,0x09,0x88,0x19,0x89,0x12,0xF1,0x2A,0x28,
|
||||||
|
0x8C,0x25,0x99,0xA4,0x98,0x39,0xA1,0x00,0xD0,0x58,0xAA,0x59,0x01,0x0C,0x00,0x2B,
|
||||||
|
0x00,0x08,0x89,0x6B,0x69,0x90,0x01,0x90,0x98,0x12,0xB3,0xF3,0xA0,0x89,0x02,0x3B,
|
||||||
|
0x0C,0x50,0xA9,0x4E,0x6B,0x19,0x28,0x09,0xA2,0x08,0x2F,0x20,0x88,0x92,0x8A,0x11,
|
||||||
|
0xC4,0x93,0xF1,0x18,0x88,0x11,0xF2,0x80,0x92,0xA8,0x02,0xA8,0xB7,0xB3,0xA3,0xA0,
|
||||||
|
0x88,0x1A,0x40,0xE2,0x91,0x19,0x88,0x18,0x91,0x83,0xC1,0xB5,0x92,0xA9,0xC6,0x90,
|
||||||
|
0x01,0xC2,0x81,0x98,0x03,0xF0,0x00,0x2C,0x2A,0x92,0x2C,0x83,0x1F,0x3A,0x29,0x00,
|
||||||
|
0xB8,0x70,0xAB,0x69,0x18,0x89,0x10,0x0D,0x12,0x0B,0x88,0x4A,0x3A,0x9B,0x70,0xA8,
|
||||||
|
0x28,0x2F,0x2A,0x3A,0x1B,0x85,0x88,0x8B,0x6A,0x29,0x00,0x91,0x91,0x1B,0x7C,0x29,
|
||||||
|
0x01,0x88,0x90,0x19,0x2B,0x2B,0x00,0x39,0xA8,0x5E,0x21,0x89,0x91,0x09,0x3A,0x6F,
|
||||||
|
0x2A,0x18,0x18,0x8B,0x50,0x89,0x2B,0x19,0x49,0x88,0x29,0xF5,0x89,0x08,0x09,0x12,
|
||||||
|
0xAA,0x15,0xB0,0x82,0xAC,0x38,0x00,0x3F,0x81,0x10,0xB0,0x49,0xA2,0x81,0x3A,0xC8,
|
||||||
|
0x87,0x90,0xC4,0xA3,0x99,0x19,0x83,0xE1,0x84,0xE2,0xA2,0x90,0x80,0x93,0xB5,0xC4,
|
||||||
|
0xB3,0xA1,0x0A,0x18,0x92,0xC4,0xA0,0x93,0x0C,0x3A,0x18,0x01,0x1E,0x20,0xB1,0x82,
|
||||||
|
0x8C,0x03,0xB5,0x2E,0x82,0x19,0xB2,0x1B,0x1B,0x6B,0x4C,0x19,0x12,0x8B,0x5A,0x11,
|
||||||
|
0x0C,0x3A,0x2C,0x18,0x3D,0x08,0x2A,0x5C,0x18,0x00,0x88,0x3D,0x29,0x80,0x2A,0x09,
|
||||||
|
0x00,0x7A,0x0A,0x10,0x0B,0x69,0x98,0x10,0x81,0x3F,0x00,0x18,0x19,0x91,0xB7,0x9A,
|
||||||
|
0x28,0x8A,0x48,0x92,0xF3,0xA2,0x88,0x98,0x87,0xA1,0x88,0x80,0x81,0x95,0xD1,0xA3,
|
||||||
|
0x1B,0x1C,0x39,0x10,0xA1,0x2A,0x0B,0x7A,0x4B,0x80,0x13,0xC1,0xD1,0x2B,0x2A,0x85,
|
||||||
|
0xB2,0xA2,0x93,0xB2,0xD3,0x80,0xD1,0x18,0x08,0x08,0xB7,0x98,0x81,0x3F,0x01,0x88,
|
||||||
|
0x01,0xE2,0x00,0x9A,0x59,0x08,0x10,0xC3,0x99,0x84,0xA9,0xA5,0x91,0x91,0x91,0x80,
|
||||||
|
0xB5,0x94,0xC0,0x01,0x98,0x09,0x84,0xB0,0x80,0x7A,0x08,0x18,0x90,0xA8,0x6A,0x1C,
|
||||||
|
0x39,0x2A,0xB7,0x98,0x19,0x10,0x2A,0xA1,0x10,0xBD,0x39,0x18,0x2D,0x39,0x3F,0x10,
|
||||||
|
0x3F,0x01,0x09,0x19,0x0A,0x38,0x8C,0x40,0xB3,0xB4,0x93,0xAD,0x20,0x2B,0xD4,0x81,
|
||||||
|
0xC3,0xB0,0x39,0xA0,0x23,0xD8,0x04,0xB1,0x9B,0xA7,0x1A,0x92,0x08,0xA5,0x88,0x81,
|
||||||
|
0xE2,0x01,0xB8,0x01,0x81,0xC1,0xC7,0x90,0x92,0x80,0xA1,0x97,0xA0,0xA2,0x82,0xB8,
|
||||||
|
0x18,0x00,0x9C,0x78,0x98,0x83,0x0B,0x0B,0x32,0x7D,0x19,0x10,0xA1,0x19,0x09,0x0A,
|
||||||
|
0x78,0xA8,0x10,0x1B,0x29,0x29,0x1A,0x14,0x2F,0x88,0x4A,0x1B,0x10,0x10,0xAB,0x79,
|
||||||
|
0x0D,0x49,0x18,0xA0,0x02,0x1F,0x19,0x3A,0x2B,0x11,0x8A,0x88,0x79,0x8A,0x20,0x49,
|
||||||
|
0x9B,0x58,0x0B,0x28,0x18,0xA9,0x3A,0x7D,0x00,0x29,0x88,0x82,0x3D,0x1A,0x38,0xBA,
|
||||||
|
0x15,0x09,0xAA,0x51,0x8B,0x83,0x3C,0x8A,0x58,0x1B,0xB5,0x01,0xBB,0x50,0x19,0x99,
|
||||||
|
0x24,0xCA,0x21,0x1B,0xA2,0x87,0xA8,0xB1,0x68,0xA1,0xA6,0xA2,0xA8,0x29,0x8B,0x24,
|
||||||
|
0xB4,0xE2,0x92,0x8A,0x00,0x19,0x93,0xB5,0xB4,0xB1,0x81,0xB1,0x03,0x9A,0x82,0xA7,
|
||||||
|
0x90,0xD6,0xA0,0x80,0x1B,0x29,0x01,0xA4,0xE1,0x18,0x0A,0x2A,0x29,0x92,0xC7,0xA8,
|
||||||
|
0x81,0x19,0x89,0x30,0x10,0xE0,0x30,0xB8,0x10,0x0C,0x1A,0x79,0x1B,0xA7,0x80,0xA0,
|
||||||
|
0x00,0x0B,0x28,0x18,0xB1,0x85,0x1E,0x00,0x20,0xA9,0x18,0x18,0x1C,0x13,0xBC,0x15,
|
||||||
|
0x99,0x2E,0x12,0x00,0xE1,0x00,0x0B,0x3B,0x21,0x90,0x06,0xC9,0x2A,0x49,0x0A,0x18,
|
||||||
|
0x20,0xD1,0x3C,0x08,0x00,0x83,0xC9,0x41,0x8E,0x18,0x08,0x02,0xA0,0x09,0xA4,0x7B,
|
||||||
|
0x90,0x19,0x2A,0x10,0x2A,0xA8,0x71,0xBA,0x10,0x4A,0x0E,0x22,0xB2,0xB2,0x1B,0x8C,
|
||||||
|
0x78,0x1A,0xB5,0x93,0xA9,0x1B,0x49,0x19,0x29,0xA3,0xC6,0x88,0xAA,0x32,0x0D,0x1B,
|
||||||
|
0x22,0x08,0xC2,0x18,0xB9,0x79,0x3F,0x01,0x10,0xA9,0x84,0x1C,0x09,0x21,0xB0,0xA7,
|
||||||
|
0x0A,0x99,0x50,0x0C,0x81,0x28,0x8B,0x48,0x2E,0x00,0x08,0x99,0x38,0x5B,0x88,0x14,
|
||||||
|
0xA9,0x08,0x11,0xAA,0x72,0xC1,0xB3,0x09,0x8A,0x05,0x91,0xF2,0x81,0xA1,0x09,0x02,
|
||||||
|
0xF2,0x92,0x99,0x1A,0x49,0x80,0xC5,0x90,0x90,0x18,0x09,0x12,0xA1,0xF2,0x81,0x98,
|
||||||
|
0xC6,0x91,0xA0,0x11,0xA0,0x94,0xB4,0xF2,0x81,0x8B,0x03,0x80,0xD2,0x93,0xA8,0x88,
|
||||||
|
0x69,0xA0,0x03,0xB8,0x88,0x32,0xBC,0x97,0x80,0xB1,0x3B,0x1A,0xA6,0x00,0xD1,0x01,
|
||||||
|
0x0B,0x3B,0x30,0x9B,0x31,0x3E,0x92,0x19,0x8A,0xD3,0x5C,0x1B,0x41,0xA0,0x93,0xA2,
|
||||||
|
0xAF,0x39,0x4C,0x01,0x92,0xA8,0x81,0x3C,0x0D,0x78,0x98,0x00,0x19,0x0A,0x20,0x2D,
|
||||||
|
0x29,0x3C,0x1B,0x48,0x88,0x99,0x7A,0x2D,0x29,0x2A,0x82,0x80,0xA8,0x49,0x3E,0x19,
|
||||||
|
0x11,0x98,0x82,0x9A,0x3B,0x28,0x2F,0x20,0x4C,0x90,0x29,0x19,0x9A,0x7A,0x29,0x28,
|
||||||
|
0x98,0x88,0x33,0xCD,0x11,0x3A,0xC1,0xA4,0xA0,0xC4,0x82,0xC8,0x50,0x98,0xB2,0x21,
|
||||||
|
0xC0,0xB6,0x98,0x82,0x80,0x9C,0x23,0x00,0xF8,0x30,0xA8,0x1A,0x68,0xA8,0x86,0x9A,
|
||||||
|
0x01,0x2A,0x0A,0x97,0x91,0xC1,0x18,0x89,0x02,0x83,0xE0,0x01,0x8B,0x29,0x30,0xE2,
|
||||||
|
0x91,0x0B,0x18,0x3B,0x1C,0x11,0x28,0xAC,0x78,0x80,0x93,0x91,0xA9,0x49,0x8B,0x87,
|
||||||
|
0x90,0x99,0x3D,0x5A,0x81,0x08,0xA1,0x11,0x2F,0x1A,0x21,0x9B,0x15,0xA2,0xB0,0x11,
|
||||||
|
0xC0,0x91,0x5B,0x98,0x24,0xA2,0xF2,0x92,0x8B,0x6A,0x18,0x81,0xB5,0xB1,0x88,0x4C,
|
||||||
|
0x00,0x00,0xA4,0xC1,0x2B,0x1A,0x59,0x0A,0x02,0x80,0x1E,0x02,0x08,0xB3,0x80,0x9A,
|
||||||
|
0x23,0xB8,0xF2,0x84,0xAB,0x01,0x48,0x90,0xA7,0x90,0x0A,0x29,0x09,0x95,0x99,0xA0,
|
||||||
|
0x59,0x2B,0x00,0x97,0xB0,0x29,0x89,0x2A,0x03,0xD0,0xB7,0x1B,0x81,0x00,0xA6,0xB1,
|
||||||
|
0x90,0x09,0x48,0xC0,0x11,0x00,0x8A,0x00,0x5B,0x83,0x9A,0x18,0x2F,0x3C,0x18,0x11,
|
||||||
|
0xA9,0x04,0x1A,0x4F,0x01,0x98,0x81,0x09,0x09,0x4A,0x18,0xB4,0xA2,0x0B,0x59,0x90,
|
||||||
|
0x3B,0x49,0xBC,0x40,0x6A,0x88,0x3A,0x08,0x3E,0x3A,0x80,0x93,0xB0,0xE1,0x5A,0x00,
|
||||||
|
0xA4,0xB3,0xE3,0x90,0x0D,0x38,0x09,0x82,0xC4,0xA1,0xB1,0x4C,0x18,0x10,0x91,0xB2,
|
||||||
|
0x13,0xEA,0x34,0x99,0x88,0xA6,0x89,0x92,0x91,0xC1,0x20,0xB2,0xC2,0x86,0xD2,0xB3,
|
||||||
|
0x80,0xB2,0x08,0x09,0x87,0x91,0xC0,0x11,0x89,0x90,0x28,0xB9,0x79,0x19,0xA4,0x82,
|
||||||
|
0xD0,0x03,0x0C,0xA3,0xA5,0xB2,0xB2,0x1B,0x29,0x13,0xF1,0xB4,0x81,0x9D,0x38,0x00,
|
||||||
|
0xC4,0xA1,0x89,0x59,0x1A,0x81,0xA4,0xA9,0x1C,0x6A,0x19,0x02,0xB1,0x1A,0x4A,0x0B,
|
||||||
|
0x78,0x89,0x81,0x1C,0x2A,0x29,0x4A,0xA3,0x3E,0x1C,0x49,0x1A,0x08,0x21,0xAE,0x28,
|
||||||
|
0x4B,0x19,0x20,0x8C,0x10,0x3A,0xAB,0x26,0x8B,0x18,0x59,0x99,0x13,0xA2,0xAB,0x79,
|
||||||
|
0x2F,0x18,0x10,0xB2,0x80,0x1B,0x4D,0x5A,0x80,0x82,0x98,0x81,0x80,0x09,0xA5,0x90,
|
||||||
|
0x91,0x03,0xC2,0xE2,0x81,0xA8,0x82,0x09,0xC6,0xA3,0xB1,0x08,0x5B,0x08,0x05,0xD1,
|
||||||
|
0xA2,0x89,0x2A,0x28,0x91,0xA6,0x88,0xB0,0x49,0x80,0x09,0x08,0x88,0x07,0xB8,0x05,
|
||||||
|
0x99,0x81,0x88,0x18,0xE2,0x00,0xC3,0x18,0x0D,0x10,0x30,0xD0,0x93,0x8A,0x09,0x10,
|
||||||
|
0x2F,0x11,0x90,0xA1,0x20,0x9B,0xB1,0x73,0xC8,0x94,0x98,0x3B,0x01,0x0C,0x30,0x19,
|
||||||
|
0xF8,0x12,0x90,0xBA,0x78,0x0A,0x11,0x98,0xA0,0x79,0x8A,0x30,0x2B,0xC2,0x11,0x0D,
|
||||||
|
0x09,0x7A,0x00,0x82,0xB9,0x01,0x7A,0x89,0x21,0x09,0xA1,0x0A,0x7C,0x10,0x88,0xB5,
|
||||||
|
0x88,0x0A,0x2B,0x69,0x1A,0x10,0xA0,0x5B,0x19,0x1A,0x10,0x19,0x1A,0x6C,0x20,0x90,
|
||||||
|
0xA5,0x98,0x1B,0x0A,0x69,0x82,0xD1,0x18,0x09,0x19,0x2A,0x93,0xD4,0x9A,0x01,0x49,
|
||||||
|
0xA2,0xA2,0x82,0xD8,0x22,0xAA,0x97,0xA9,0x2D,0x38,0x2A,0xB6,0x80,0x90,0x0A,0x3C,
|
||||||
|
0x82,0x94,0xB8,0x21,0x0E,0x2A,0x22,0xB8,0x00,0x4F,0x2B,0x3A,0x81,0xA1,0x29,0x2C,
|
||||||
|
0x6A,0x13,0xD1,0xA2,0x98,0x28,0x0C,0x01,0xD5,0x08,0xA9,0x31,0xB3,0xB0,0xA7,0xB0,
|
||||||
|
0x29,0x1B,0x87,0xA2,0xA1,0xB2,0x4A,0x89,0x11,0xC3,0xF3,0x98,0x08,0x03,0xA0,0xA3,
|
||||||
|
0xC5,0x90,0xB3,0xB5,0xB4,0xB8,0x02,0x91,0x91,0xD3,0xA4,0xC1,0x1B,0x82,0x28,0xA4,
|
||||||
|
0xD1,0x94,0x8A,0x28,0x08,0x03,0xE0,0x80,0xD4,0x90,0x91,0xA1,0x3B,0x3D,0x02,0xE4,
|
||||||
|
0xA1,0x92,0x89,0x1A,0x4B,0x95,0xB3,0x90,0x99,0x6A,0x0A,0x30,0xA1,0x93,0xA6,0xA9,
|
||||||
|
0x85,0x8B,0x82,0x10,0xB1,0xA3,0x94,0xF8,0x38,0x9A,0x30,0x1A,0x8B,0xA7,0x89,0x01,
|
||||||
|
0x5B,0x19,0x18,0x11,0xF0,0x18,0x1C,0x39,0x19,0x0C,0x12,0x1C,0x2A,0x7B,0x3A,0x88,
|
||||||
|
0x2B,0x18,0x2B,0x5C,0x20,0x92,0x8D,0x38,0x8A,0x3A,0x5B,0x2E,0x3A,0x2B,0x10,0x12,
|
||||||
|
0xBB,0x6A,0x4D,0x18,0x10,0xB1,0x81,0x2A,0x8B,0x79,0x80,0x01,0x0A,0x09,0x5B,0x2D,
|
||||||
|
0x84,0x8A,0x08,0x02,0xA2,0x91,0x82,0xE8,0x50,0x9B,0x85,0xA3,0xB0,0xA3,0x1B,0x02,
|
||||||
|
0x18,0xF3,0xA2,0x88,0xAB,0x53,0xD1,0xB4,0xA3,0x09,0x09,0x18,0xD4,0x08,0xB0,0x09,
|
||||||
|
0x58,0xD1,0x82,0x89,0x81,0x1A,0x18,0x05,0xB9,0xC3,0x30,0xC0,0x95,0x80,0xC3,0x89,
|
||||||
|
0x89,0x13,0x88,0xF2,0x93,0x0E,0x18,0x01,0x92,0xA5,0xB8,0x2A,0x39,0xAA,0x33,0x9A,
|
||||||
|
0xB1,0x11,0xF5,0xA1,0xA1,0x0A,0x50,0xB8,0x03,0xC4,0xA0,0x4E,0x29,0x10,0x88,0xC2,
|
||||||
|
0x1A,0x39,0x1D,0x28,0x98,0x94,0x0E,0x10,0x2A,0x3C,0x02,0x2D,0x1B,0x4B,0x3B,0x49,
|
||||||
|
0x19,0xA9,0x48,0x2F,0x29,0x10,0x89,0x02,0x0C,0x10,0x09,0xB9,0x70,0x1B,0x8A,0x50,
|
||||||
|
0xA8,0x2B,0x49,0x89,0x69,0x88,0x95,0x89,0x90,0x92,0x4C,0x19,0x82,0xC1,0x01,0x80,
|
||||||
|
0xA0,0x2B,0x7A,0x81,0x10,0xC2,0xB7,0x98,0x88,0x19,0x2C,0x03,0xB1,0xA4,0xA1,0x0C,
|
||||||
|
0x3B,0x78,0x88,0x85,0xB1,0xA0,0x1B,0x3A,0x4A,0x08,0x94,0x81,0xF1,0x80,0x00,0x0C,
|
||||||
|
0x59,0x09,0x18,0x90,0xA6,0x92,0x8C,0x1A,0x79,0x92,0xA8,0x00,0x81,0x2E,0x2A,0x13,
|
||||||
|
0xA2,0xB0,0xA5,0x88,0x88,0x89,0x11,0x19,0xA0,0xF3,0x82,0xB0,0x83,0x5F,0x2A,0x01,
|
||||||
|
0xA1,0x94,0xB0,0x09,0x78,0x98,0xA3,0xA6,0xA0,0x91,0x80,0x93,0x98,0xC1,0x12,0x18,
|
||||||
|
0xC9,0x17,0xA0,0xA0,0x1A,0x21,0x80,0x99,0xD4,0x30,0x9D,0x00,0x10,0x2F,0x08,0x1C,
|
||||||
|
0x21,0x08,0xB4,0xC3,0x2B,0xA9,0x52,0xD2,0xA3,0xD1,0x09,0x10,0x8B,0x24,0x92,0xD1,
|
||||||
|
0x80,0x19,0xA0,0x2C,0x12,0x49,0xAA,0xB6,0x95,0xB8,0x08,0x3A,0x2B,0x01,0xF3,0xB3,
|
||||||
|
0x0B,0x09,0x79,0x18,0xA2,0xA4,0xA0,0x18,0x0C,0x20,0x08,0xA9,0x16,0x0C,0x00,0x1B,
|
||||||
|
0x08,0x2B,0x7B,0x01,0x01,0xB9,0x59,0x19,0x8B,0x45,0xA8,0x80,0x0C,0x1A,0x41,0x1E,
|
||||||
|
0x00,0x28,0xA8,0x5A,0x00,0xC1,0x49,0x99,0x21,0x1D,0x08,0x85,0x99,0x95,0x89,0x90,
|
||||||
|
0x11,0x90,0xD1,0x28,0xB2,0xA7,0x99,0x81,0x02,0xAC,0x13,0x81,0xB2,0xA6,0xA9,0x28,
|
||||||
|
0x1C,0xB1,0x33,0xD1,0xC1,0x58,0xA8,0x14,0xB0,0xB7,0x91,0xA0,0x82,0x89,0xC2,0x28,
|
||||||
|
0xA1,0xB2,0x49,0xD2,0x94,0xC8,0x12,0x80,0x99,0x85,0x08,0xD3,0x09,0xA2,0xB3,0x1E,
|
||||||
|
0x08,0x21,0xB9,0x23,0xB4,0xAB,0x41,0xAC,0x87,0x09,0xA2,0xC5,0x0B,0x2A,0x5A,0x91,
|
||||||
|
0x20,0x9A,0x89,0x78,0x9B,0x31,0x89,0x80,0x29,0x0A,0xB7,0x3C,0x98,0x48,0x1D,0x00,
|
||||||
|
0x01,0xB0,0x20,0x2F,0x29,0x4A,0x89,0x94,0x1C,0x88,0x28,0x2B,0x10,0x88,0x9A,0x71,
|
||||||
|
0x9A,0x08,0x4A,0x2F,0x18,0x2B,0x18,0x02,0xA8,0x4B,0x7A,0x99,0x48,0x80,0xA8,0x20,
|
||||||
|
0x1D,0x40,0xA8,0x10,0x08,0xA8,0xC5,0x88,0xC2,0x18,0x88,0x2A,0x12,0xF3,0x82,0xD8,
|
||||||
|
0x20,0x0A,0x09,0xA6,0x98,0x04,0xB9,0x11,0x18,0xC3,0xE1,0x29,0xA1,0x11,0xC1,0x03,
|
||||||
|
0xE2,0x9A,0x33,0xA9,0xB5,0x98,0x92,0xA1,0x02,0xF8,0x21,0xA8,0x10,0x02,0xC1,0xB7,
|
||||||
|
0x1B,0x90,0x5B,0x3C,0x83,0x93,0xE0,0x19,0x1A,0x11,0x11,0xF1,0x92,0x89,0x19,0x2C,
|
||||||
|
0x2C,0x41,0x99,0x92,0x90,0x3F,0x18,0x4B,0x00,0x08,0xD2,0x01,0xB2,0xAA,0x78,0x09,
|
||||||
|
0x01,0x91,0xA2,0x98,0x2F,0x3A,0x2C,0x01,0x00,0x93,0xE0,0x28,0x2C,0x2B,0x01,0x12,
|
||||||
|
0xE1,0x80,0xB3,0x3D,0x3A,0x0A,0x50,0x98,0xC2,0xA0,0x11,0xAA,0x30,0x87,0x90,0xC2,
|
||||||
|
0x29,0x88,0x38,0xC8,0xB5,0x90,0xBA,0x70,0x1A,0x02,0x94,0xD0,0x80,0x1A,0x82,0xA6,
|
||||||
|
0xB0,0x91,0x18,0xB3,0x00,0x13,0xF1,0xA2,0xC1,0x82,0xB0,0x00,0x15,0x0B,0xD3,0x02,
|
||||||
|
0xA8,0x91,0x2B,0x1F,0x49,0x88,0xA6,0x80,0x88,0x08,0x1B,0xA5,0x80,0xB9,0x06,0x0B,
|
||||||
|
0x90,0x21,0x9D,0x48,0x18,0xA0,0x15,0xC9,0x82,0x2B,0x1A,0x42,0x9A,0xC4,0x39,0xBC,
|
||||||
|
0x69,0x00,0xA0,0x29,0x8C,0x39,0x59,0x08,0x09,0x49,0xA9,0x6B,0x81,0x00,0x98,0xB0,
|
||||||
|
0x68,0x3D,0x81,0x88,0x18,0x19,0x1D,0x12,0x80,0xB2,0x3A,0x3F,0x85,0x92,0xD0,0x00,
|
||||||
|
0x0A,0x19,0x12,0xF1,0x02,0x9B,0x19,0x40,0xB9,0x11,0x02,0xF2,0x1A,0x08,0x94,0x0A,
|
||||||
|
0xC2,0x83,0x0B,0xB4,0xA4,0xC0,0x32,0xD8,0x86,0x98,0x90,0x95,0x89,0xA3,0x83,0xC2,
|
||||||
|
0x92,0xE1,0x92,0x82,0xD9,0x03,0x08,0xA9,0x85,0x92,0xA2,0x80,0xE0,0x30,0x8B,0xB3,
|
||||||
|
0x87,0x89,0x90,0x83,0xA0,0x08,0x92,0x93,0x3E,0xAB,0x43,0x89,0xE3,0x80,0x83,0x2F,
|
||||||
|
0x00,0xA3,0x80,0xC9,0x22,0x3F,0x08,0x81,0x0B,0x33,0x9A,0xA3,0x7B,0x0C,0x29,0x4A,
|
||||||
|
0x1B,0x21,0xAA,0x70,0x1B,0x0D,0x48,0x1A,0x81,0x88,0xB1,0x39,0x3F,0x08,0x58,0xA0,
|
||||||
|
0x81,0x1A,0x1A,0x2B,0x6D,0x11,0x0A,0x91,0x01,0x1A,0x98,0x5A,0x0C,0x03,0xB1,0x84,
|
||||||
|
0xA3,0xAD,0x58,0x2A,0xA1,0x84,0xB1,0xA0,0x5C,0x2B,0x13,0xA8,0x95,0x83,0xE8,0x10,
|
||||||
|
0x81,0xB0,0x00,0xC2,0x96,0xA0,0x91,0x00,0x2C,0x90,0x30,0xF2,0x80,0xA8,0x39,0x21,
|
||||||
|
0xC1,0x03,0xAC,0x39,0x7C,0x29,0x91,0x1A,0x00,0x19,0x2C,0x3A,0x93,0xB0,0x29,0x8F,
|
||||||
|
0x28,0x02,0x93,0xF3,0xA9,0x01,0x03,0xE0,0x08,0x09,0x1D,0x58,0xA1,0x83,0xA9,0x6B,
|
||||||
|
0x2A,0x3C,0x21,0x89,0xC2,0x2C,0x4B,0x8A,0x50,0x81,0x98,0xA8,0x32,0x0C,0x8E,0x24,
|
||||||
|
0x0B,0x1A,0x81,0x92,0xA1,0x4F,0x18,0x3A,0x0A,0xB4,0x18,0x2E,0x39,0x82,0x19,0xD3,
|
||||||
|
0xD0,0x28,0x1B,0x11,0x98,0x07,0xAA,0x28,0x00,0x88,0xB4,0x89,0x1B,0x1F,0x22,0x00,
|
||||||
|
0xB3,0xC9,0x33,0xAB,0x2B,0xB5,0x48,0x98,0x98,0xA7,0x10,0xD2,0xC1,0x23,0xCA,0x93,
|
||||||
|
0xC6,0x80,0xA1,0x88,0x02,0x89,0xE2,0x09,0x38,0xBA,0x40,0x89,0x21,0xD8,0x49,0x10,
|
||||||
|
0x8D,0x02,0x90,0xC3,0x9A,0x24,0x89,0x08,0x84,0xA5,0x9C,0x10,0x11,0x9C,0x88,0x30,
|
||||||
|
0x3C,0xA1,0x94,0x58,0x8C,0x0B,0x69,0x29,0x9A,0x81,0x12,0x2B,0x8B,0x79,0x94,0xB0,
|
||||||
|
0xC1,0x84,0xC2,0x99,0x25,0x99,0x11,0xA2,0x93,0xE4,0x99,0x80,0x0A,0x00,0x10,0xB7,
|
||||||
|
0xB0,0x31,0xBA,0x3C,0x21,0xB3,0xF1,0x18,0xA0,0x2A,0x20,0xA3,0x06,0xE8,0x28,0xA1,
|
||||||
|
0xB4,0x08,0x0B,0x11,0x4B,0xB7,0x90,0xA5,0x98,0x3D,0x19,0x02,0xA1,0xC4,0xB2,0x19,
|
||||||
|
0x28,0xC0,0xA5,0x92,0xB1,0xA3,0x0A,0x0A,0x08,0x2B,0x70,0xC4,0xB3,0x00,0xBC,0x4B,
|
||||||
|
0x39,0x12,0xE3,0xA0,0x00,0x3F,0x18,0x29,0x94,0xD1,0x19,0x09,0x00,0xA1,0x83,0x99,
|
||||||
|
0x9B,0x35,0x80,0xC4,0xB1,0x6A,0x1A,0x1C,0x29,0x38,0x0E,0x19,0x5A,0x1A,0x82,0x8A,
|
||||||
|
0x59,0x2A,0x2E,0x20,0x88,0xA8,0x3A,0x38,0x3D,0x00,0xB3,0x29,0xAD,0x49,0x10,0x0C,
|
||||||
|
0x01,0x01,0xA3,0x8F,0x85,0x09,0x1B,0x88,0x10,0xA3,0xD2,0x90,0x3C,0x5C,0x39,0x03,
|
||||||
|
0xD1,0xA0,0x00,0x2A,0x0B,0x04,0xA7,0x90,0xA0,0x11,0x90,0x99,0x83,0xB4,0xB1,0xF1,
|
||||||
|
0x84,0x88,0x90,0x18,0x18,0xD3,0xD2,0xB3,0xA0,0x1A,0x21,0xA7,0xB2,0xB3,0x92,0x9A,
|
||||||
|
0x22,0xB9,0x28,0x38,0xBD,0x87,0x2A,0xB1,0x13,0x0D,0x0A,0x38,0xC9,0x24,0xC0,0x19,
|
||||||
|
0x23,0x0F,0x01,0x88,0xC0,0x2A,0x82,0x18,0x28,0xF0,0x18,0x2A,0x29,0x4B,0x35,0xB8,
|
||||||
|
0xA3,0x9D,0x18,0x1B,0x40,0x00,0x9A,0x5C,0x3A,0x09,0x2F,0x38,0x8A,0x3B,0x3B,0x11,
|
||||||
|
0x5C,0x19,0x2B,0x4A,0x08,0x0A,0x3D,0x20,0x4F,0x3A,0x19,0x2A,0x18,0x4D,0x1B,0x3A,
|
||||||
|
0x11,0x0D,0x3A,0x3C,0x4B,0x93,0x81,0xAA,0x6B,0x4A,0x18,0x00,0xC3,0xC3,0x9A,0x59,
|
||||||
|
0x2A,0x1B,0xA7,0xA1,0x81,0x88,0x88,0x58,0xB2,0xB1,0x2B,0x83,0xD4,0x81,0x08,0x0F,
|
||||||
|
0x00,0x20,0xC2,0xE2,0x80,0x08,0x1C,0x29,0x04,0xB1,0xA2,0x01,0x1C,0x91,0x00,0x0C,
|
||||||
|
0x49,0xB0,0x43,0xF2,0x99,0x39,0x3F,0x00,0x81,0x94,0xC1,0x09,0x1A,0x69,0x90,0x80,
|
||||||
|
0x94,0xAA,0x20,0x2A,0x91,0xB1,0x39,0x7A,0x38,0xD1,0x10,0x8A,0x8C,0x5A,0x01,0xB5,
|
||||||
|
0x98,0x80,0x2A,0x0B,0x32,0x92,0xF1,0x81,0x9A,0x23,0x8A,0xA3,0xB7,0x09,0x03,0x08,
|
||||||
|
0xD0,0x94,0x9A,0x09,0x01,0x93,0xB7,0xC2,0x8C,0x3A,0x83,0x99,0x05,0xA0,0x0B,0x29,
|
||||||
|
0x93,0xE5,0x80,0x89,0x38,0x90,0x8A,0xD7,0xA1,0x19,0x1B,0x48,0x98,0x92,0xC3,0xA1,
|
||||||
|
0x09,0x3F,0x02,0x0C,0x22,0xC3,0xB2,0xA1,0x01,0x9F,0x4A,0x01,0xA3,0xD3,0xB0,0x28,
|
||||||
|
0x3F,0x29,0x20,0xA2,0xC2,0xB1,0x08,0x5A,0x98,0x13,0xD2,0xC1,0x01,0xB2,0x80,0x3D,
|
||||||
|
0x03,0xC1,0x89,0x96,0x90,0x90,0x3A,0x1A,0x9A,0x32,0xB6,0xA2,0x8E,0x4A,0x28,0x8A,
|
||||||
|
0x84,0xA2,0x8A,0x2D,0x49,0x09,0x88,0x18,0x30,0x9D,0x2C,0x23,0xB1,0x0C,0x92,0x2D,
|
||||||
|
0x39,0x82,0xC4,0x2E,0x10,0x1A,0x10,0xB9,0x48,0x19,0x39,0xBA,0x34,0xDA,0x2D,0x48,
|
||||||
|
0x1A,0xA6,0x98,0x83,0x9A,0x1D,0x38,0x04,0xD0,0x18,0x90,0x2C,0x11,0x93,0xD3,0x9A,
|
||||||
|
0x11,0x08,0x82,0xF1,0x01,0xA0,0x2A,0x93,0xD3,0xB4,0xB8,0x82,0x2F,0x11,0xA3,0xB3,
|
||||||
|
0xA8,0x3B,0x09,0x23,0x96,0xC8,0x3B,0x3F,0x93,0x82,0xA1,0x90,0x3F,0x28,0x81,0xD1,
|
||||||
|
0x93,0x08,0x2D,0x18,0x91,0xB3,0xB5,0x98,0x2A,0x2B,0x84,0xB1,0x5B,0x8A,0x31,0x18,
|
||||||
|
0x80,0x8B,0x7E,0x39,0x2B,0x02,0xC1,0x8B,0x6C,0x49,0x09,0x10,0xA1,0x08,0x01,0x0C,
|
||||||
|
0x20,0xA1,0x09,0x4F,0x18,0x00,0x01,0xA0,0x5C,0x1B,0x5B,0x10,0x92,0x90,0x2B,0x5A,
|
||||||
|
0x3D,0x18,0x91,0x19,0x98,0x2D,0x39,0x89,0x2D,0x3A,0x48,0x2C,0x11,0xB5,0x9A,0x19,
|
||||||
|
0x5B,0x28,0x90,0x95,0x98,0x89,0x2B,0x40,0x08,0x90,0xF3,0x0A,0x08,0xA6,0x80,0x91,
|
||||||
|
0xB2,0xA0,0x02,0xF2,0xA1,0xB7,0x89,0x81,0x82,0x91,0xB1,0x21,0xAB,0x32,0xE9,0x04,
|
||||||
|
0xA2,0x8D,0x12,0x91,0xA3,0xA3,0xD2,0x8B,0x39,0xD1,0x84,0xE2,0x90,0x00,0x2B,0x29,
|
||||||
|
0xA3,0xD4,0xA1,0x91,0x1D,0x5A,0x08,0x19,0x11,0x99,0x08,0x18,0x49,0x0F,0x18,0x10,
|
||||||
|
0x82,0xF1,0x00,0x89,0x2F,0x3A,0x01,0xB3,0xC2,0x81,0x3F,0x29,0x08,0x10,0xA1,0xA1,
|
||||||
|
0x3B,0x5D,0x19,0x28,0x0B,0x38,0x82,0x91,0x19,0xBD,0x3B,0x7A,0x80,0x12,0xB3,0xE0,
|
||||||
|
0x0B,0x6A,0x01,0x88,0xA4,0x08,0x0B,0x08,0x59,0x80,0x80,0x1D,0x49,0x89,0x00,0x84,
|
||||||
|
0x99,0x1A,0x2B,0x32,0xE3,0xB4,0xA9,0x3A,0x99,0x31,0xE3,0xAA,0x58,0x3B,0x88,0x95,
|
||||||
|
0xC0,0x18,0x4A,0x09,0x30,0xF2,0xA3,0x1C,0x1B,0x49,0x00,0xD3,0xB2,0xA0,0x18,0x11,
|
||||||
|
0x92,0xD3,0xB2,0x91,0x80,0xE7,0xA1,0x91,0x98,0x19,0x22,0xC2,0xD2,0x18,0x8D,0x3B,
|
||||||
|
0x10,0xA5,0x91,0x98,0x02,0x3E,0x80,0x01,0x90,0xAA,0x13,0xF1,0x02,0xD1,0x08,0x19,
|
||||||
|
0x49,0xB4,0x91,0xB4,0x99,0x2A,0x0C,0x32,0xC0,0x05,0x88,0x0B,0x80,0x2C,0x81,0x10,
|
||||||
|
0x0B,0x51,0xA9,0x19,0x05,0xBF,0x28,0x20,0xE1,0x90,0x80,0x28,0x19,0x08,0x26,0xB1,
|
||||||
|
0xA1,0x18,0x88,0x2A,0xF0,0x12,0x8A,0xB3,0x14,0x1B,0xD4,0xD8,0x10,0x08,0x8A,0x17,
|
||||||
|
0xA0,0x98,0x2B,0x3A,0x29,0x48,0xA4,0x99,0x0E,0x4A,0x12,0x8B,0x31,0x8B,0x4E,0x1A,
|
||||||
|
0x11,0xB5,0x89,0x91,0x29,0x89,0xC2,0x97,0x90,0x0A,0x19,0x11,0x91,0xC1,0xD5,0x08,
|
||||||
|
0x89,0x20,0x91,0xB1,0x1A,0x2D,0x18,0x29,0xD2,0x3B,0x3E,0x3A,0x2A,0x90,0x82,0x1C,
|
||||||
|
0x49,0x3B,0x93,0xB6,0xC8,0x4C,0x02,0x91,0x93,0xF2,0x88,0x2D,0x28,0x81,0x82,0xC1,
|
||||||
|
0x89,0x2D,0x6B,0x19,0x82,0x80,0x18,0x8B,0x39,0x39,0xC8,0x3A,0x6A,0x0A,0x22,0xD2,
|
||||||
|
0x09,0x2C,0x1A,0x68,0x92,0xE2,0x89,0x2A,0x2A,0x30,0xC2,0xA3,0xB4,0x1D,0x2A,0x09,
|
||||||
|
0x93,0x18,0xF2,0x89,0x28,0xB3,0x01,0x8F,0x18,0x11,0xA1,0x93,0x90,0xD1,0x7A,0x20,
|
||||||
|
0xC3,0xA2,0xA8,0x88,0x1D,0x28,0xA5,0xA2,0xA2,0x0B,0x29,0x2B,0x87,0xC1,0x80,0x0A,
|
||||||
|
0x19,0x01,0x12,0xF1,0x10,0x80,0x0A,0x18,0x08,0x2F,0x4A,0x02,0x89,0x1B,0x29,0x5D,
|
||||||
|
0x4C,0x08,0x82,0xA1,0x0A,0x3A,0x4B,0x29,0xC6,0xC3,0x09,0x09,0x88,0x39,0x98,0x82,
|
||||||
|
0xA5,0x1A,0x30,0x11,0xBD,0x3F,0x12,0x8B,0x28,0xC3,0x88,0x3F,0x2B,0x3B,0x48,0xA1,
|
||||||
|
0x80,0x8A,0x4D,0x39,0x01,0x93,0xA2,0xF1,0x19,0x19,0x0A,0x02,0xB2,0x8B,0x24,0xD2,
|
||||||
|
0x4B,0x12,0xC8,0x2E,0x10,0xB5,0x89,0x01,0x09,0x1C,0x2A,0x03,0xD4,0x91,0x98,0x99,
|
||||||
|
0x11,0x2B,0xE4,0x00,0x00,0x01,0xE0,0xA5,0x89,0x99,0x31,0x18,0xD0,0xB7,0x98,0x18,
|
||||||
|
0x0A,0x10,0x94,0xC2,0x90,0x18,0x00,0x99,0x87,0xA0,0x90,0x2A,0x3C,0x02,0xB8,0xC1,
|
||||||
|
0x79,0x1A,0x20,0x08,0xA1,0xD2,0x1C,0x29,0x03,0xD1,0x29,0x99,0x2C,0x50,0xB3,0xD1,
|
||||||
|
0x08,0x09,0x3C,0x10,0x04,0xB2,0x0D,0x2B,0x59,0x80,0x90,0x01,0x0F,0x3A,0x18,0x01,
|
||||||
|
0xA2,0x9B,0x5B,0x3D,0x81,0x03,0xD2,0x98,0x59,0x90,0x81,0x92,0xB4,0x8B,0x1B,0x40,
|
||||||
|
0xB2,0xB5,0x08,0x4B,0x01,0x09,0xD1,0x91,0x8B,0x7A,0x10,0xB3,0xC3,0x99,0x49,0x1A,
|
||||||
|
0x29,0xB5,0xA2,0xAB,0x40,0x81,0x19,0xB7,0xB0,0x20,0x2B,0xD4,0x88,0xA1,0x91,0x3C,
|
||||||
|
0x82,0x37,0xD3,0xB1,0x8A,0x1B,0x30,0xB3,0xF4,0xA1,0x91,0x09,0x10,0x03,0xD0,0x83,
|
||||||
|
0xA9,0x8F,0x10,0x01,0x90,0x18,0x80,0x20,0x2B,0xF1,0x28,0x99,0x2A,0x41,0xF0,0x12,
|
||||||
|
0xAA,0x83,0x82,0xD1,0xC1,0x08,0x89,0x59,0x09,0x83,0x87,0xB0,0x2A,0x4D,0x18,0x09,
|
||||||
|
0x19,0xB3,0x4B,0x3F,0x39,0x19,0x09,0x01,0x89,0x03,0x1F,0x00,0x1A,0x0B,0x10,0x68,
|
||||||
|
0xA0,0x18,0x8C,0x6A,0x09,0x08,0x97,0xA1,0x81,0x1B,0x2B,0x4C,0x03,0xB4,0xA8,0x92,
|
||||||
|
0x4B,0x3C,0xA1,0x81,0x95,0xA8,0x81,0x12,0xBB,0x92,0x45,0xB9,0x93,0xF4,0x88,0x0A,
|
||||||
|
0x2D,0x28,0x00,0xA3,0xA3,0x8A,0x3F,0x48,0xB1,0x92,0xB4,0xA8,0x30,0x80,0xD3,0x80,
|
||||||
|
0xD1,0x19,0x3B,0xC4,0x81,0xC1,0x29,0x0D,0x20,0x13,0xC8,0xB4,0x4C,0x09,0x00,0x82,
|
||||||
|
0xC2,0x3B,0x0D,0x30,0x0B,0x12,0xF0,0x1B,0x20,0x0A,0xA6,0x80,0x0A,0x4A,0x4A,0x80,
|
||||||
|
0x94,0xB1,0x2E,0x3B,0x1A,0x10,0x93,0x10,0x4C,0x3D,0x08,0x82,0xC9,0x19,0x6A,0x2B,
|
||||||
|
0x38,0xD1,0x08,0x19,0x2A,0x5A,0x82,0xB1,0x8D,0x29,0x78,0x09,0x82,0x0A,0x2C,0x1B,
|
||||||
|
0x19,0x41,0xB8,0x8C,0x79,0x2B,0x11,0x88,0x82,0x91,0xDC,0x28,0x11,0xB0,0x11,0x18,
|
||||||
|
0xC9,0x62,0xA1,0x91,0x98,0x3B,0x3A,0xB0,0xF4,0x01,0xC0,0x29,0x39,0xF8,0x95,0x91,
|
||||||
|
0x88,0x88,0x91,0x03,0xA1,0xE2,0x18,0x82,0xD1,0xA2,0xD1,0x80,0x19,0x20,0x83,0xB1,
|
||||||
|
0xE3,0x80,0x91,0x4D,0x1A,0x03,0xB2,0x09,0x18,0xD1,0x19,0x09,0x92,0xA6,0xA0,0xB6,
|
||||||
|
0xB2,0x8B,0x38,0x10,0x42,0xD3,0xD0,0xA8,0x20,0x2C,0x10,0x01,0xB1,0xB4,0xAB,0x5B,
|
||||||
|
0x79,0x80,0x10,0x1A,0xA8,0x3D,0x18,0x20,0xB3,0x8F,0x18,0x01,0x00,0x09,0xF3,0x89,
|
||||||
|
0x69,0x88,0x81,0x91,0x08,0xE1,0x1A,0x08,0x11,0x81,0x1E,0x29,0xA0,0x01,0x00,0x90,
|
||||||
|
0x3E,0x7B,0x18,0x82,0xC3,0xA1,0x2A,0x2C,0x5B,0x81,0xA5,0x90,0x81,0x00,0x0B,0x1A,
|
||||||
|
0x1C,0x2C,0x32,0xC0,0xF3,0x80,0x2D,0x2A,0x10,0x02,0xE4,0xC1,0x89,0x4A,0x09,0x01,
|
||||||
|
0x03,0xD2,0x98,0x2A,0x39,0x8A,0x89,0x26,0xB1,0xB2,0x12,0xC0,0x0A,0x5A,0x18,0x98,
|
||||||
|
0xF3,0x92,0x99,0x99,0x79,0x01,0xB5,0xA1,0x80,0x80,0x90,0x83,0xA0,0xE2,0x81,0x29,
|
||||||
|
0x93,0x8A,0x0A,0x6A,0x1F,0x18,0x02,0xC8,0x01,0x19,0x3B,0x4A,0x98,0x17,0xA8,0x0D,
|
||||||
|
0x38,0xA1,0x91,0x10,0xA2,0x2B,0x4C,0xA6,0x81,0xBA,0x21,0x4C,0x80,0x21,0xD1,0x92,
|
||||||
|
0x2C,0x08,0x30,0x9F,0x93,0x2A,0x89,0x03,0x8B,0x87,0x0A,0x0D,0x12,0x98,0xA4,0x93,
|
||||||
|
0xBB,0x59,0x18,0xA1,0x32,0xE9,0x84,0x08,0x8A,0x02,0xA1,0x91,0x4B,0xB4,0x20,0x88,
|
||||||
|
0xF0,0x3A,0x1A,0x88,0x87,0xB1,0x92,0x0A,0x08,0x6B,0x83,0xC3,0x91,0xC0,0x2B,0x79,
|
||||||
|
0x08,0x8A,0x84,0xA0,0x89,0x40,0x1B,0xA1,0x39,0x98,0x17,0xC2,0xA2,0x12,0xCD,0x20,
|
||||||
|
0x89,0x92,0x25,0xB0,0x2D,0x3A,0x8B,0x58,0x2A,0xA0,0x4C,0x08,0x30,0xAE,0x82,0x59,
|
||||||
|
0x89,0x1A,0x10,0xC2,0x18,0x2C,0x40,0x1E,0x01,0xA3,0x8A,0x81,0x2C,0x29,0x29,0xA9,
|
||||||
|
0x13,0x51,0xAD,0x12,0x89,0x8F,0x18,0x2C,0x39,0x00,0xC1,0x10,0x3C,0x2A,0x41,0xC8,
|
||||||
|
0xA2,0x91,0x0A,0x6C,0x10,0x12,0x88,0xE8,0x30,0x91,0x81,0xD8,0x01,0x1B,0x0D,0x07,
|
||||||
|
0x00,0xA8,0x92,0x0A,0x28,0xD2,0xC3,0x02,0xAA,0x94,0x81,0xB4,0xB3,0x1A,0x0B,0x13,
|
||||||
|
0xF9,0x16,0xA1,0x8A,0x59,0x19,0x02,0xC1,0x91,0x8B,0x3D,0x18,0x3B,0xA4,0x94,0x80,
|
||||||
|
0x99,0x88,0x1C,0x79,0x0A,0x02,0x03,0xF8,0x90,0x39,0x5B,0x19,0x02,0xC3,0x90,0xBB,
|
||||||
|
0x58,0x6A,0x09,0x02,0x89,0x91,0x88,0x1A,0x69,0x8A,0x19,0x15,0xA0,0xA2,0x00,0x9A,
|
||||||
|
0x6B,0x49,0x88,0xA3,0x92,0xBB,0x6B,0x3D,0x38,0x01,0x98,0x91,0x3F,0x09,0x18,0x20,
|
||||||
|
0x90,0x80,0xAC,0x70,0x91,0x9B,0x51,0x09,0x88,0x99,0x14,0x8B,0x98,0x83,0x79,0xA0,
|
||||||
|
0x99,0x13,0x01,0x19,0xE0,0x83,0x0B,0xB0,0x0C,0x31,0x95,0xB5,0xC2,0x8A,0x39,0x20,
|
||||||
|
0x80,0x39,0xF3,0xB1,0x10,0x88,0x5E,0x18,0x94,0xA1,0x88,0xA1,0x98,0x15,0xAA,0x39,
|
||||||
|
0xD4,0x84,0xC0,0xA2,0xA2,0x0C,0x81,0x86,0xB5,0xA1,0xB1,0x14,0x1B,0xB1,0x02,0x92,
|
||||||
|
0xC3,0xE0,0x88,0x11,0xAA,0x69,0x18,0x81,0xA3,0xB0,0x01,0xBF,0x2A,0x31,0x93,0xF1,
|
||||||
|
0x00,0x89,0x18,0x19,0x11,0xD3,0xE0,0x10,0x18,0xB1,0x18,0x24,0x9A,0x2B,0xA4,0xC0,
|
||||||
|
0xB0,0x31,0x6C,0x19,0xB4,0x12,0xA8,0xEA,0x58,0x10,0x8B,0x93,0x82,0x88,0x9A,0x41,
|
||||||
|
0x10,0xC3,0xEA,0x41,0xA9,0x9C,0x34,0xA1,0x2A,0x79,0xA2,0x01,0xA8,0xB3,0x28,0xCC,
|
||||||
|
0x41,0x9A,0xB3,0x4B,0xB3,0x27,0x8B,0x83,0x2B,0x2F,0x08,0x28,0xB2,0x80,0x2C,0x30,
|
||||||
|
0x5E,0x09,0x12,0x9B,0x09,0x22,0x5B,0x19,0x8A,0x11,0x59,0x99,0xA4,0x32,0xCD,0x18,
|
||||||
|
0x08,0x10,0x85,0xB3,0xB4,0x1E,0x88,0x28,0x8A,0x11,0x09,0xC0,0x79,0x80,0x91,0x3B,
|
||||||
|
0x80,0x10,0x0F,0x01,0x80,0x91,0x19,0x3D,0x92,0x28,0xA8,0x37,0x9A,0x0A,0x3A,0x8A,
|
||||||
|
0x45,0xA9,0xA4,0x00,0xAA,0x09,0x3D,0x59,0x20,0xE1,0x08,0x98,0x90,0x59,0x10,0x09,
|
||||||
|
0xA3,0xC3,0x93,0x99,0x2B,0x69,0x11,0xD1,0xB1,0xA4,0x91,0x3C,0x89,0x83,0xF0,0x10,
|
||||||
|
0x91,0xA1,0x89,0x59,0x05,0x99,0x93,0x94,0xC8,0x08,0x0A,0x09,0x17,0xB1,0x83,0xC1,
|
||||||
|
0x91,0x40,0xA2,0xC2,0x98,0xC3,0xBA,0x28,0x23,0x0F,0x80,0x50,0xB8,0x19,0x10,0x96,
|
||||||
|
0x98,0x8C,0x05,0x98,0x19,0x29,0x2B,0x3B,0x0A,0xE2,0x01,0x0F,0x3C,0x38,0x08,0x09,
|
||||||
|
0x81,0x4A,0x6C,0x08,0x00,0x88,0x98,0x38,0x2C,0x5A,0x1B,0x20,0x1A,0x39,0xB0,0x09,
|
||||||
|
0xCB,0x5B,0x49,0x09,0x71,0x00,0xC1,0x0E,0x08,0x38,0x0C,0x02,0x10,0x0E,0x10,0x8A,
|
||||||
|
0x48,0x19,0x90,0x92,0x0D,0xA3,0x98,0x3B,0x79,0x19,0x01,0x10,0xE1,0x80,0x19,0x2B,
|
||||||
|
0x10,0xF2,0x02,0xAB,0x84,0x9A,0x29,0xB4,0x80,0x92,0x03,0x88,0x95,0xD0,0x03,0x90,
|
||||||
|
0xA0,0xC7,0xA1,0xB0,0xA2,0x02,0x18,0xB5,0xD4,0x01,0xC0,0x08,0xA2,0x93,0xA8,0xA0,
|
||||||
|
0xC3,0x20,0xF3,0x90,0x00,0xD5,0x08,0x89,0xA5,0x80,0xA0,0x81,0x82,0xC2,0x09,0xD1,
|
||||||
|
0x13,0xCB,0x03,0x84,0x91,0xE1,0x1B,0x12,0x08,0xAB,0x87,0x18,0xAB,0x58,0x89,0x28,
|
||||||
|
0x81,0xC9,0x33,0xA9,0x80,0x2E,0x20,0x83,0xB9,0x20,0x3B,0x9E,0x7A,0x08,0x81,0x18,
|
||||||
|
0x0B,0x88,0x79,0x80,0x8B,0x00,0x12,0x0E,0x89,0x51,0x1B,0x81,0xA0,0x3A,0x01,0xAF,
|
||||||
|
0x11,0x28,0xBA,0x35,0x98,0x88,0x52,0xC0,0x83,0x2F,0xA9,0x11,0x0A,0x19,0x25,0xD0,
|
||||||
|
0x30,0x9C,0x08,0x21,0x98,0x81,0x2A,0xF3,0x2A,0x80,0xB6,0x2B,0x08,0x93,0xE9,0x02,
|
||||||
|
0x81,0x8C,0x21,0x00,0xA6,0xA9,0x94,0x01,0x8F,0x80,0x94,0x98,0x93,0xB4,0x00,0x08,
|
||||||
|
0xC0,0x14,0x98,0xB3,0xB4,0xC1,0x09,0x18,0xA7,0x00,0xA3,0xC8,0x0A,0x3C,0x19,0x96,
|
||||||
|
0x83,0xC1,0x99,0x19,0x4A,0x85,0x80,0xC1,0x91,0x99,0x90,0x2A,0x17,0x95,0x99,0x88,
|
||||||
|
0x12,0xAE,0x39,0x08,0x92,0x84,0xB0,0xA8,0x79,0x09,0x19,0x01,0xB2,0xA3,0x8F,0x28,
|
||||||
|
0x2B,0xA2,0x40,0x82,0xA0,0x4C,0xA9,0x39,0x8D,0x81,0x70,0x88,0xA0,0x1A,0x49,0x2D,
|
||||||
|
0x1A,0x26,0xA8,0x98,0x08,0x29,0x0B,0x12,0x96,0xB1,0xB2,0x3A,0x13,0x9B,0x60,0xA0,
|
||||||
|
0x88,0xB2,0x34,0xEA,0x1A,0x2A,0x79,0x98,0x10,0x04,0x8C,0x1C,0x81,0x04,0x8C,0x83,
|
||||||
|
0x19,0x2F,0x81,0x93,0x98,0x10,0x08,0x30,0x2A,0xFA,0x05,0x08,0x2A,0x89,0x91,0xA3,
|
||||||
|
0xFA,0x11,0x11,0x00,0x8C,0x04,0x8A,0x2A,0xB5,0x10,0xA9,0xC2,0x3D,0x1B,0x32,0x04,
|
||||||
|
0x0A,0x1A,0x09,0x40,0x1F,0x92,0x1D,0x2A,0x91,0x10,0x30,0x2F,0x0B,0x68,0x99,0xA2,
|
||||||
|
0x92,0x88,0x78,0xA9,0x20,0x28,0xE2,0x92,0x1A,0x99,0x4B,0x19,0x22,0xA1,0xE2,0x21,
|
||||||
|
0x2F,0x98,0x29,0x18,0x91,0x08,0xB0,0x79,0x1A,0x82,0x3B,0xB1,0xA7,0x8A,0xB3,0x98,
|
||||||
|
0x5B,0x23,0xCA,0x42,0x83,0xF0,0x90,0x18,0x98,0x08,0xB4,0x20,0xA3,0xC0,0x43,0xD8,
|
||||||
|
0x80,0x81,0xA3,0x99,0xD9,0xA7,0x19,0x90,0x10,0x05,0xB1,0x8B,0x02,0xA4,0xBD,0x23,
|
||||||
|
0x93,0x8A,0x99,0x4B,0x03,0xC1,0xF8,0x38,0x09,0x2B,0x14,0xD0,0x03,0x8A,0x2A,0x39,
|
||||||
|
0xB9,0x97,0x90,0xAA,0x50,0x01,0x99,0x51,0xD1,0x09,0x1A,0xB5,0x00,0x8B,0x93,0x08,
|
||||||
|
0x98,0x11,0xF9,0x85,0x2B,0x08,0x96,0x89,0x90,0x2A,0x12,0x4A,0xD8,0x85,0x2B,0x0E,
|
||||||
|
0x10,0x00,0x01,0xB1,0x9B,0x69,0x1A,0x90,0x40,0xB8,0x01,0x08,0x0A,0x2C,0x09,0x14,
|
||||||
|
0x4B,0xE2,0x82,0x88,0xB1,0x78,0x0A,0x01,0xC2,0x93,0x19,0xCE,0x20,0x3C,0x82,0xB4,
|
||||||
|
0x1B,0x20,0x8C,0x3B,0x29,0xAB,0x86,0x23,0xD8,0x81,0x9A,0x5A,0x49,0xB0,0x16,0xA0,
|
||||||
|
0xB0,0x28,0x1B,0x13,0x93,0xE4,0xA2,0xA9,0x08,0x5A,0xB3,0x12,0xC1,0xE1,0x10,0x88,
|
||||||
|
0x01,0x0C,0x92,0x08,0x89,0xB7,0x88,0x81,0x10,0x9A,0x17,0xA0,0xB0,0x13,0x99,0xE0,
|
||||||
|
0x39,0x31,0xD2,0xB2,0x80,0x0B,0x2D,0x49,0x80,0x01,0xB0,0x06,0x09,0x0C,0x3A,0x69,
|
||||||
|
0xA0,0x08,0xB2,0xA1,0x69,0x2B,0x5A,0x81,0x92,0xBA,0x21,0xB1,0x7D,0x10,0x80,0x08,
|
||||||
|
0x88,0x82,0x32,0x0D,0xB0,0x1A,0x1C,0x21,0x94,0xA9,0x58,0xB9,0x5A,0x4A,0xA0,0x13,
|
||||||
|
0xA9,0x80,0x7C,0x00,0x20,0x8A,0x04,0x0C,0x00,0x82,0x2A,0xB2,0xAC,0x4B,0x69,0xA0,
|
||||||
|
0xA6,0x81,0x9B,0x19,0x38,0x8B,0x17,0xB2,0x81,0x2A,0xBB,0x94,0x29,0xA2,0x15,0xBA,
|
||||||
|
0x97,0xA3,0xB9,0x79,0x01,0xB2,0x02,0xF1,0x90,0x0A,0x29,0x11,0x88,0xE5,0xA0,0x81,
|
||||||
|
0x19,0x91,0x90,0x28,0xB3,0x14,0xD0,0xB5,0x91,0x9A,0x29,0x0B,0x07,0xA2,0xB3,0x01,
|
||||||
|
0x9D,0x28,0x41,0xD0,0x91,0x90,0x82,0x1A,0xA8,0x44,0x9A,0xA9,0x21,0xE3,0xA9,0x4B,
|
||||||
|
0x19,0x78,0x89,0x83,0xA3,0xB9,0x5A,0x3D,0x80,0x82,0xA2,0xA0,0x6C,0x10,0x20,0x8B,
|
||||||
|
0x93,0x8B,0x0E,0x33,0xA9,0xB1,0x68,0x8A,0x31,0xAC,0x94,0xB4,0x8B,0x32,0x0B,0xB4,
|
||||||
|
0x81,0x91,0x1D,0x33,0xD9,0x31,0xE1,0x8B,0x3B,0x30,0x12,0x49,0xD2,0x8E,0x29,0x18,
|
||||||
|
0x8A,0x92,0x02,0xAA,0x59,0x1C,0x32,0x88,0x01,0x23,0xFB,0x83,0x29,0xDA,0x59,0x01,
|
||||||
|
0x81,0x92,0xE1,0x18,0x8A,0x1D,0x30,0x93,0xF1,0x00,0x01,0x0B,0x39,0x92,0x89,0xA0,
|
||||||
|
0x11,0x5B,0xE0,0x82,0x09,0x13,0xAA,0xB4,0x16,0xD8,0x91,0x2A,0x29,0x84,0x1B,0xC5,
|
||||||
|
0x98,0x98,0x31,0x98,0x99,0x17,0xA9,0x20,0x92,0xC3,0x18,0x9D,0x20,0x3D,0x89,0x94,
|
||||||
|
0xA2,0x1C,0x5C,0x29,0x39,0xA0,0xB3,0x00,0x0C,0x4C,0x48,0x92,0x0A,0x91,0x85,0x9A,
|
||||||
|
0x01,0x82,0x1F,0x10,0x99,0x15,0xC1,0xA0,0x39,0x1A,0x1D,0x85,0xB4,0x90,0x1A,0x2A,
|
||||||
|
0x4B,0x01,0xB2,0x93,0xBE,0x12,0x83,0xC9,0x18,0x09,0x20,0x78,0xF1,0x08,0x19,0x88,
|
||||||
|
0x3A,0x83,0xB3,0xA9,0x93,0x7A,0x0A,0x96,0x98,0x00,0xA8,0x3A,0x30,0x92,0xF2,0x9B,
|
||||||
|
0x3D,0x38,0x92,0x92,0xC3,0xB8,0x6B,0x29,0x01,0x01,0xB2,0x2F,0x09,0x19,0x18,0x01,
|
||||||
|
0x3B,0x7B,0x10,0xA1,0x90,0x39,0x0F,0x38,0x0A,0xB5,0xA4,0x89,0x8B,0x6A,0x2B,0x12,
|
||||||
|
0xC8,0x90,0x40,0x2A,0x9E,0x22,0x88,0x18,0x09,0x3A,0xC3,0xE8,0x09,0x59,0x08,0x12,
|
||||||
|
0x94,0xD0,0x1A,0x2C,0x38,0x00,0xA1,0x83,0xE8,0x08,0x3A,0x08,0x10,0x9E,0x83,0x1D,
|
||||||
|
0x92,0x19,0x2C,0x39,0x3B,0x59,0x04,0xE1,0x80,0x08,0x8D,0x21,0x81,0xB2,0xB2,0x02,
|
||||||
|
0x99,0x91,0xA4,0xD6,0x98,0x99,0x03,0x80,0x98,0xA7,0x91,0x09,0xA1,0xB2,0xB3,0xE1,
|
||||||
|
0x12,0x92,0xB1,0x81,0x06,0x99,0x0A,0x23,0xC4,0xB1,0xF2,0x89,0x19,0x3A,0x94,0x82,
|
||||||
|
0xE0,0x89,0x38,0x0B,0xA4,0xA5,0x80,0x80,0x8C,0x34,0xB9,0xA9,0x23,0x13,0xB9,0xC1,
|
||||||
|
0xC7,0x1B,0x89,0x10,0x20,0x11,0xE3,0xA8,0x4B,0x0B,0x40,0x91,0x90,0x1B,0x5F,0x2A,
|
||||||
|
0x18,0x82,0x91,0x0B,0x4A,0x28,0xCA,0x40,0x80,0x5B,0x2C,0x13,0xB0,0x8A,0xA9,0x5A,
|
||||||
|
0x58,0x89,0x82,0x88,0x2E,0x3B,0x31,0xA1,0x9B,0x01,0x7A,0x2C,0x01,0x91,0x93,0x3F,
|
||||||
|
0x88,0x39,0x10,0xF1,0x91,0x8B,0x48,0x0A,0x12,0xE3,0xA8,0x18,0x28,0x92,0x97,0x98,
|
||||||
|
0x99,0x19,0xA1,0x11,0xB6,0x88,0x3B,0x10,0xD3,0xC3,0xA1,0x2A,0x8A,0x49,0x04,0xF1,
|
||||||
|
0x91,0x02,0x8A,0x89,0x04,0xF1,0x98,0x80,0x18,0x12,0xE3,0x81,0x98,0x80,0x01,0xB3,
|
||||||
|
0xF2,0x99,0x12,0x2A,0xB5,0xB3,0x92,0xAA,0x19,0x50,0xB2,0xC3,0x92,0xD0,0x2B,0x68,
|
||||||
|
0x93,0x99,0xC0,0x2C,0x3E,0x80,0x20,0x08,0x93,0x0D,0x2A,0x31,0x8D,0x02,0x2B,0x91,
|
||||||
|
0x08,0x0A,0x03,0x2C,0x3C,0x52,0xB9,0xA0,0x12,0xBF,0x3A,0x29,0x01,0x88,0xC0,0x6A,
|
||||||
|
0x3C,0x0A,0x49,0x18,0x0B,0x39,0x2B,0x69,0x0A,0x84,0x2A,0x2A,0x1C,0x2A,0xC3,0x8C,
|
||||||
|
0x19,0x50,0x09,0x91,0xA7,0x8D,0x18,0x1A,0x28,0x00,0xA0,0x94,0x10,0x1F,0x20,0x90,
|
||||||
|
0x8A,0x12,0xD0,0x1A,0x5A,0x81,0x04,0xBC,0x23,0x10,0xE0,0x90,0x90,0x18,0x1A,0xA6,
|
||||||
|
0x12,0xB1,0xD0,0x4A,0x08,0x82,0x92,0xB6,0x9A,0x0A,0x12,0x88,0xC3,0xC5,0x8A,0x89,
|
||||||
|
0x20,0xB5,0x93,0x0B,0x18,0x00,0x09,0xF2,0x88,0x2A,0x4A,0x08,0x05,0xB2,0xA9,0x3B,
|
||||||
|
0x5D,0x28,0xA4,0xB1,0x00,0x19,0x19,0x7A,0xA3,0xB3,0x0A,0x90,0xA1,0xC4,0x80,0xBA,
|
||||||
|
0x50,0x13,0xC1,0xC2,0x9A,0x2A,0x7B,0x28,0x84,0xC1,0x09,0x3B,0x4E,0x20,0x91,0xA1,
|
||||||
|
0x18,0xAB,0x79,0x10,0xB4,0x08,0x9A,0x11,0x2B,0xF0,0x93,0xAA,0x01,0x6A,0x01,0x93,
|
||||||
|
0x80,0xB8,0x2A,0x5B,0x10,0x80,0x89,0x4A,0x5B,0x92,0x15,0xB2,0xA0,0x2F,0x19,0x93,
|
||||||
|
0xB8,0x95,0x80,0x1C,0x21,0xA9,0x02,0x0B,0xA0,0x5A,0x18,0x98,0x39,0x1B,0x68,0x00,
|
||||||
|
0x91,0x91,0x9C,0x39,0x3E,0x18,0x84,0xB3,0x9B,0x7A,0x08,0x18,0x0A,0xB5,0x91,0x0B,
|
||||||
|
0x28,0x39,0x19,0x90,0x0A,0x50,0xAC,0x11,0x01,0xAB,0x88,0x52,0x1B,0x83,0xC4,0xA2,
|
||||||
|
0x9A,0xAB,0x03,0x90,0x19,0x93,0x81,0x08,0x92,0x9A,0x68,0x98,0x19,0x39,0xC1,0x92,
|
||||||
|
0x8A,0x38,0x4E,0x02,0xB1,0x90,0xC3,0x18,0x2B,0x04,0xC3,0xD2,0x91,0x90,0x81,0x89,
|
||||||
|
0x13,0xF1,0x88,0x93,0xA2,0x00,0x91,0xC0,0x5B,0x21,0x99,0x93,0x06,0x9A,0x1B,0x48,
|
||||||
|
0x99,0xB7,0x90,0x89,0x18,0x1B,0x11,0xA4,0xB2,0x81,0x9A,0x08,0x97,0x98,0x91,0x10,
|
||||||
|
0xB8,0x06,0xA2,0xA0,0x29,0x2B,0x21,0xC2,0xD1,0x10,0x1A,0x4A,0x29,0xF1,0x98,0x29,
|
||||||
|
0x1B,0x31,0x10,0xA0,0xA1,0x1D,0x5A,0x29,0xB2,0x82,0xA8,0x0F,0x28,0x21,0x09,0x91,
|
||||||
|
0x82,0x4D,0x10,0xA3,0xB0,0x89,0x4C,0x39,0xA0,0xA4,0xA1,0x89,0x1E,0x28,0x29,0xA3,
|
||||||
|
0xC3,0x2D,0x19,0x01,0x49,0x01,0x9B,0x0C,0x21,0xC2,0xA2,0x93,0x7C,0x2A,0x10,0x90,
|
||||||
|
|
||||||
|
/* Source: 08HH.ROM */
|
||||||
|
/* Length: 384 / 0x00000180 */
|
||||||
|
|
||||||
|
0x75,0xF2,0xAB,0x7D,0x7E,0x5C,0x3B,0x4B,0x3C,0x4D,0x4A,0x02,0xB3,0xC5,0xE7,0xE3,
|
||||||
|
0x92,0xB3,0xC4,0xB3,0xC3,0x8A,0x3B,0x5D,0x5C,0x3A,0x84,0xC2,0x91,0xA4,0xE7,0xF7,
|
||||||
|
0xF7,0xF4,0xA1,0x1B,0x49,0xA5,0xB1,0x1E,0x7F,0x5A,0x00,0x89,0x39,0xB7,0xA8,0x3D,
|
||||||
|
0x4A,0x84,0xE7,0xF7,0xE2,0x2D,0x4C,0x3A,0x4E,0x7D,0x04,0xB0,0x2D,0x4B,0x10,0x80,
|
||||||
|
0xA3,0x99,0x10,0x0E,0x59,0x93,0xC4,0xB1,0x81,0xC4,0xA2,0xB2,0x88,0x08,0x3F,0x3B,
|
||||||
|
0x28,0xA6,0xC3,0xA2,0xA2,0xC5,0xC1,0x3F,0x7E,0x39,0x81,0x93,0xC2,0xA3,0xE5,0xD2,
|
||||||
|
0x80,0x93,0xB8,0x6D,0x49,0x82,0xD4,0xA1,0x90,0x01,0xA0,0x09,0x04,0xE3,0xB2,0x91,
|
||||||
|
0xB7,0xB3,0xA8,0x2A,0x03,0xF3,0xA1,0x92,0xC5,0xC3,0xB2,0x0B,0x30,0xB3,0x8E,0x6D,
|
||||||
|
0x4A,0x01,0xB4,0xB4,0xC4,0xC3,0x99,0x3B,0x12,0xE3,0xA1,0x88,0x82,0xB4,0x9A,0x5C,
|
||||||
|
0x3A,0x18,0x93,0xC3,0xB3,0xB4,0xA8,0x19,0x04,0xF3,0xA8,0x3B,0x10,0xA2,0x88,0xA5,
|
||||||
|
0xB2,0x0B,0x6D,0x4B,0x10,0x91,0x89,0x3C,0x18,0x18,0xA6,0xC4,0xC3,0x98,0x19,0x2B,
|
||||||
|
0x20,0x91,0xA0,0x4E,0x28,0x93,0xB3,0xC2,0x92,0xA9,0x5A,0x96,0xC4,0xC2,0x09,0x01,
|
||||||
|
0xC4,0xA1,0x92,0xC4,0xA1,0x89,0x10,0xA3,0xA1,0x90,0x1C,0x5A,0x01,0xC5,0xA1,0x92,
|
||||||
|
0xD4,0xB3,0xC4,0xC4,0xC3,0xA1,0x88,0x1A,0x28,0x89,0x3C,0x3A,0x3D,0x29,0x00,0x93,
|
||||||
|
0xB0,0x3D,0x28,0x80,0x91,0x82,0xE3,0x99,0x2A,0x11,0xD6,0xC3,0x99,0x29,0x82,0xC4,
|
||||||
|
0xC3,0xA1,0x0A,0x3B,0x3D,0x3A,0x02,0xC3,0xA2,0x99,0x3B,0x2C,0x7C,0x28,0x81,0xA3,
|
||||||
|
0xB2,0xA3,0xB1,0x08,0x1A,0x3C,0x18,0x2E,0x4C,0x39,0xA5,0xB3,0xB4,0xC2,0x88,0x08,
|
||||||
|
0x19,0x0A,0x49,0xB7,0xB3,0xA2,0xA1,0x92,0xA1,0x93,0xB1,0x0C,0x7D,0x39,0x93,0xB3,
|
||||||
|
0xB1,0x1A,0x19,0x5D,0x28,0xA6,0xC4,0xB2,0x90,0x09,0x2A,0x18,0x1B,0x5B,0x28,0x88,
|
||||||
|
0x2C,0x29,0x82,0xA0,0x18,0x91,0x2D,0x29,0x2B,0x5C,0x4C,0x3B,0x4C,0x28,0x80,0x92,
|
||||||
|
0x90,0x09,0x2B,0x28,0x1D,0x6B,0x11,0xC5,0xB2,0x0B,0x39,0x09,0x4D,0x28,0x88,0x00,
|
||||||
|
0x1B,0x28,0x94,0xE3,0xA0,0x1A,0x28,0xB5,0xB4,0xB3,0xB2,0x93,0xE2,0x91,0x92,0xD4,
|
||||||
|
0xA0,0x1B,0x4A,0x01,0xA1,0x88,0x2D,0x5C,0x3B,0x28,0x08,0x93,0xD4,0xB2,0x91,0xB4,
|
||||||
|
0xA0,0x3E,0x3B,0x4B,0x3B,0x29,0x08,0x93,0x9B,0x7B,0x3A,0x19,0x00,0x80,0x80,0xA0,
|
||||||
|
|
||||||
|
/* Source: 10TOM.ROM */
|
||||||
|
/* Length: 640 / 0x00000280 */
|
||||||
|
|
||||||
|
0x77,0x27,0x87,0x01,0x2D,0x4F,0xC3,0xC1,0x92,0x91,0x89,0x59,0x83,0x1A,0x32,0xC2,
|
||||||
|
0x95,0xB1,0x81,0x88,0x81,0x4A,0x3D,0x11,0x9E,0x0B,0x88,0x0C,0x18,0x3B,0x11,0x11,
|
||||||
|
0x91,0x00,0xA0,0xE2,0x0A,0x48,0x13,0x24,0x81,0x48,0x1B,0x39,0x1C,0x83,0x84,0xA1,
|
||||||
|
0xD1,0x8E,0x8A,0x0B,0xC0,0x98,0x92,0xB8,0x39,0x90,0x10,0x92,0xF0,0xB5,0x88,0x32,
|
||||||
|
0x49,0x51,0x21,0x03,0x82,0x10,0x8A,0x7A,0x09,0x00,0xA2,0xCA,0x1B,0xCC,0x1C,0xB9,
|
||||||
|
0x8E,0x89,0x89,0xA1,0x89,0x92,0x29,0x11,0x60,0x40,0x14,0x22,0x32,0x78,0x40,0x01,
|
||||||
|
0x02,0x90,0x81,0xAB,0x0B,0x00,0xAF,0x99,0xCC,0xAB,0xDA,0xA9,0x99,0x1B,0x30,0x14,
|
||||||
|
0x92,0x22,0x19,0x68,0x32,0x14,0x26,0x13,0x23,0x23,0x20,0x12,0x9A,0xA8,0xB9,0xFA,
|
||||||
|
0xAA,0xCA,0xCC,0x0C,0xA8,0xAE,0x88,0xB9,0x88,0xA0,0x02,0x21,0x50,0x43,0x03,0x81,
|
||||||
|
0x2A,0x11,0x34,0x63,0x24,0x33,0x22,0x38,0x8B,0xEA,0xAE,0x99,0xA0,0x90,0x82,0x00,
|
||||||
|
0x89,0xBF,0x8A,0xE8,0xA9,0x90,0x01,0x12,0x13,0x12,0x08,0xA9,0xAA,0xC9,0x22,0x63,
|
||||||
|
0x63,0x12,0x44,0x00,0x10,0x88,0x9C,0x98,0xA1,0x85,0x03,0x32,0x36,0x80,0x89,0xDB,
|
||||||
|
0xDB,0xBB,0xB9,0xBA,0x01,0x81,0x28,0x19,0xCB,0xFA,0xBC,0x09,0x13,0x37,0x34,0x34,
|
||||||
|
0x23,0x31,0x20,0x10,0x00,0x00,0x28,0x38,0x10,0x88,0xEC,0x8D,0xCB,0xBC,0xCC,0xBB,
|
||||||
|
0xBB,0xC9,0x99,0x00,0x00,0x33,0x11,0x22,0x81,0x07,0x41,0x54,0x34,0x34,0x22,0x31,
|
||||||
|
0x00,0x88,0x9A,0x9B,0x98,0xAB,0x8E,0x9B,0xBD,0x9C,0xBC,0xBB,0xDA,0xAA,0xA9,0x99,
|
||||||
|
0x18,0x38,0x60,0x20,0x31,0x13,0x13,0x51,0x14,0x31,0x53,0x33,0x35,0x22,0x01,0x8A,
|
||||||
|
0x9C,0xA9,0xCA,0xC9,0xA8,0x00,0x10,0x81,0x9C,0x9E,0xAB,0xCC,0xAB,0xBA,0x98,0x30,
|
||||||
|
0x52,0x03,0x81,0x08,0x9C,0xAC,0xAC,0x18,0x11,0x03,0x51,0x61,0x41,0x31,0x31,0x02,
|
||||||
|
0x01,0x20,0x24,0x43,0x44,0x40,0x30,0x10,0xBC,0xBE,0xCB,0xDB,0xAB,0xBA,0x99,0x98,
|
||||||
|
0x99,0xAA,0xBD,0xAA,0xC8,0x90,0x11,0x53,0x37,0x23,0x43,0x34,0x33,0x33,0x33,0x11,
|
||||||
|
0x28,0x00,0x19,0xA9,0x9A,0xCB,0xCE,0xBB,0xEB,0xBC,0xBB,0xCA,0xBA,0xA8,0x88,0x11,
|
||||||
|
0x12,0x21,0x20,0x22,0x26,0x26,0x23,0x23,0x43,0x24,0x22,0x32,0x20,0x31,0x81,0x9A,
|
||||||
|
0xBC,0xBC,0xCB,0xBD,0x9A,0xA9,0x90,0x98,0xBA,0xCC,0xCB,0xBC,0x8B,0x88,0x22,0x35,
|
||||||
|
0x23,0x12,0x99,0x8B,0xAA,0xAA,0x89,0x82,0x93,0x31,0x42,0x23,0x23,0x21,0x32,0x11,
|
||||||
|
0x20,0x13,0x13,0x24,0x24,0x24,0x22,0x11,0x8A,0x9E,0xAC,0xAC,0xAA,0xBA,0xAA,0xAB,
|
||||||
|
0xBD,0xBC,0xCB,0xCB,0xA9,0xA8,0x91,0x12,0x44,0x43,0x44,0x34,0x34,0x42,0x33,0x42,
|
||||||
|
0x21,0x11,0x11,0x88,0x80,0xAA,0x0B,0xAC,0xCB,0xEC,0xAC,0xBA,0xCA,0xAB,0x9A,0x99,
|
||||||
|
0x80,0x91,0x09,0x08,0x10,0x22,0x44,0x43,0x44,0x33,0x43,0x22,0x13,0x21,0x22,0x20,
|
||||||
|
0x09,0x88,0xB9,0xC8,0xBB,0xAB,0xAB,0xA9,0xA9,0x9B,0x9B,0x99,0x90,0x90,0x00,0x81,
|
||||||
|
0x00,0x08,0x09,0x8A,0x9A,0xAA,0xA9,0xA9,0x99,0x90,0x80,0x01,0x80,0x00,0x09,0x31,
|
||||||
|
0x32,0x44,0x33,0x43,0x34,0x33,0x24,0x22,0x23,0x12,0x10,0x09,0x9B,0xAB,0xCA,0xCC,
|
||||||
|
0xBB,0xCB,0xDA,0xCA,0xAB,0xCA,0xAB,0xA9,0xA8,0x92,0x12,0x43,0x53,0x35,0x23,0x33,
|
||||||
|
0x43,0x43,0x52,0x22,0x22,0x21,0x01,0x09,0x89,0xA9,0xBB,0xBD,0xBC,0xCB,0xDA,0xAB,
|
||||||
|
0xAB,0xAB,0xAA,0xA9,0x99,0xA8,0x09,0x01,0x11,0x34,0x25,0x23,0x33,0x51,0x22,0x31,
|
||||||
|
0x12,0x20,0x21,0x12,0x10,0x80,0x99,0x9A,0x99,0x99,0x88,0x08,0x00,0x88,0xA9,0x99,
|
||||||
|
0x99,0x80,0x80,0x10,0x01,0x00,0x9A,0xAA,0xBB,0xBA,0xBA,0xA9,0x99,0x99,0x89,0x99,
|
||||||
|
0x99,0x00,0x01,0x33,0x35,0x24,0x23,0x34,0x23,0x33,0x34,0x33,0x43,0x32,0x21,0x88,
|
||||||
|
0xAB,0xBD,0xBB,0xDB,0xAB,0xBA,0xBB,0xDA,0xBB,0xCB,0xBB,0xBC,0xA8,0x90,0x01,0x12,
|
||||||
|
0x23,0x43,0x53,0x34,0x34,0x39,0x80,0x08,0x08,0x08,0x08,0x08,0x08,0x08,0x08,0x00,
|
||||||
|
|
||||||
|
/* Source: 20RIM.ROM */
|
||||||
|
/* Length: 128 / 0x00000080 */
|
||||||
|
|
||||||
|
0x0F,0xFF,0x73,0x8E,0x71,0xCD,0x00,0x49,0x10,0x90,0x21,0x49,0xA0,0xDB,0x02,0x3A,
|
||||||
|
0xE3,0x0A,0x50,0x98,0xC0,0x59,0xA2,0x99,0x09,0x22,0xA2,0x80,0x10,0xA8,0x5B,0xD2,
|
||||||
|
0x88,0x21,0x09,0x96,0xA8,0x10,0x0A,0xE0,0x08,0x48,0x19,0xAB,0x52,0xA8,0x92,0x0C,
|
||||||
|
0x03,0x19,0xE2,0x0A,0x12,0xC2,0x81,0x1E,0x01,0xD0,0x48,0x88,0x98,0x01,0x49,0x91,
|
||||||
|
0xAA,0x2C,0x25,0x89,0x88,0xB5,0x81,0xA2,0x9A,0x12,0x9E,0x38,0x3B,0x81,0x9B,0x59,
|
||||||
|
0x01,0x93,0xCA,0x4A,0x21,0xA0,0x3D,0x0A,0x39,0x3D,0x12,0xA8,0x3F,0x18,0x01,0x92,
|
||||||
|
0x1C,0x00,0xB2,0x48,0xB9,0x94,0xA3,0x19,0x4F,0x19,0xB2,0x32,0x90,0xBA,0x01,0xE6,
|
||||||
|
0x91,0x80,0xC1,0xA4,0x2A,0x08,0xA1,0xB1,0x25,0xD2,0x88,0x99,0x21,0x80,0x88,0x80,
|
||||||
|
};
|
||||||
|
|
@ -465,6 +465,8 @@ public:
|
||||||
// generate one sample of sound
|
// generate one sample of sound
|
||||||
void generate(output_data *output, uint32_t numsamples = 1);
|
void generate(output_data *output, uint32_t numsamples = 1);
|
||||||
|
|
||||||
|
fm_engine* debug_fm_engine() { return &m_fm; }
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
// internal helpers
|
// internal helpers
|
||||||
void update_prescale(uint8_t prescale);
|
void update_prescale(uint8_t prescale);
|
||||||
|
|
@ -546,6 +548,12 @@ public:
|
||||||
// generate one sample of sound
|
// generate one sample of sound
|
||||||
void generate(output_data *output, uint32_t numsamples = 1);
|
void generate(output_data *output, uint32_t numsamples = 1);
|
||||||
|
|
||||||
|
// get the engine
|
||||||
|
fm_engine* debug_fm_engine() { return &m_fm; }
|
||||||
|
ssg_engine* debug_ssg_engine() { return &m_ssg; }
|
||||||
|
adpcm_a_engine* debug_adpcm_a_engine() { return &m_adpcm_a; }
|
||||||
|
adpcm_b_engine* debug_adpcm_b_engine() { return &m_adpcm_b; }
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
// internal helpers
|
// internal helpers
|
||||||
void update_prescale(uint8_t prescale);
|
void update_prescale(uint8_t prescale);
|
||||||
|
|
|
||||||
|
|
@ -186,7 +186,8 @@ void DivPlatformSoundUnit::tick(bool sysTick) {
|
||||||
chan[i].freq=parent->calcFreq(chan[i].baseFreq,chan[i].pitch,false,2,chan[i].pitch2,chipClock,CHIP_FREQBASE);
|
chan[i].freq=parent->calcFreq(chan[i].baseFreq,chan[i].pitch,false,2,chan[i].pitch2,chipClock,CHIP_FREQBASE);
|
||||||
if (chan[i].pcm) {
|
if (chan[i].pcm) {
|
||||||
DivInstrument* ins=parent->getIns(chan[i].ins,DIV_INS_SU);
|
DivInstrument* ins=parent->getIns(chan[i].ins,DIV_INS_SU);
|
||||||
DivSample* sample=parent->getSample(ins->amiga.initSample);
|
// TODO: sample map?
|
||||||
|
DivSample* sample=parent->getSample(ins->amiga.getSample(chan[i].note));
|
||||||
if (sample!=NULL) {
|
if (sample!=NULL) {
|
||||||
double off=0.25;
|
double off=0.25;
|
||||||
if (sample->centerRate<1) {
|
if (sample->centerRate<1) {
|
||||||
|
|
@ -204,7 +205,7 @@ void DivPlatformSoundUnit::tick(bool sysTick) {
|
||||||
if (chan[i].keyOn) {
|
if (chan[i].keyOn) {
|
||||||
if (chan[i].pcm) {
|
if (chan[i].pcm) {
|
||||||
DivInstrument* ins=parent->getIns(chan[i].ins,DIV_INS_SU);
|
DivInstrument* ins=parent->getIns(chan[i].ins,DIV_INS_SU);
|
||||||
DivSample* sample=parent->getSample(ins->amiga.initSample);
|
DivSample* sample=parent->getSample(ins->amiga.getSample(chan[i].note));
|
||||||
if (sample!=NULL) {
|
if (sample!=NULL) {
|
||||||
unsigned int sampleEnd=sample->offSU+sample->samples;
|
unsigned int sampleEnd=sample->offSU+sample->samples;
|
||||||
if (sampleEnd>=getSampleMemCapacity(0)) sampleEnd=getSampleMemCapacity(0)-1;
|
if (sampleEnd>=getSampleMemCapacity(0)) sampleEnd=getSampleMemCapacity(0)-1;
|
||||||
|
|
|
||||||
|
|
@ -263,7 +263,7 @@ int DivPlatformSwan::dispatch(DivCommand c) {
|
||||||
dacPos=0;
|
dacPos=0;
|
||||||
dacPeriod=0;
|
dacPeriod=0;
|
||||||
if (ins->type==DIV_INS_AMIGA) {
|
if (ins->type==DIV_INS_AMIGA) {
|
||||||
dacSample=ins->amiga.initSample;
|
dacSample=ins->amiga.getSample(c.value);
|
||||||
if (dacSample<0 || dacSample>=parent->song.sampleLen) {
|
if (dacSample<0 || dacSample>=parent->song.sampleLen) {
|
||||||
dacSample=-1;
|
dacSample=-1;
|
||||||
if (dumpWrites) addWrite(0xffff0002,0);
|
if (dumpWrites) addWrite(0xffff0002,0);
|
||||||
|
|
@ -448,6 +448,7 @@ void DivPlatformSwan::muteChannel(int ch, bool mute) {
|
||||||
}
|
}
|
||||||
|
|
||||||
void DivPlatformSwan::forceIns() {
|
void DivPlatformSwan::forceIns() {
|
||||||
|
noise=0;
|
||||||
for (int i=0; i<4; i++) {
|
for (int i=0; i<4; i++) {
|
||||||
chan[i].insChanged=true;
|
chan[i].insChanged=true;
|
||||||
chan[i].freqChanged=true;
|
chan[i].freqChanged=true;
|
||||||
|
|
|
||||||
|
|
@ -260,7 +260,7 @@ int DivPlatformVERA::dispatch(DivCommand c) {
|
||||||
if (c.chan<16) {
|
if (c.chan<16) {
|
||||||
rWriteLo(c.chan,2,chan[c.chan].vol);
|
rWriteLo(c.chan,2,chan[c.chan].vol);
|
||||||
} else {
|
} else {
|
||||||
chan[16].pcm.sample=parent->getIns(chan[16].ins,DIV_INS_VERA)->amiga.initSample;
|
chan[16].pcm.sample=parent->getIns(chan[16].ins,DIV_INS_VERA)->amiga.getSample(c.value);
|
||||||
if (chan[16].pcm.sample<0 || chan[16].pcm.sample>=parent->song.sampleLen) {
|
if (chan[16].pcm.sample<0 || chan[16].pcm.sample>=parent->song.sampleLen) {
|
||||||
chan[16].pcm.sample=-1;
|
chan[16].pcm.sample=-1;
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -243,7 +243,7 @@ int DivPlatformVRC6::dispatch(DivCommand c) {
|
||||||
if (chan[c.chan].pcm) {
|
if (chan[c.chan].pcm) {
|
||||||
if (skipRegisterWrites) break;
|
if (skipRegisterWrites) break;
|
||||||
if (ins->type==DIV_INS_AMIGA) {
|
if (ins->type==DIV_INS_AMIGA) {
|
||||||
chan[c.chan].dacSample=ins->amiga.initSample;
|
chan[c.chan].dacSample=ins->amiga.getSample(c.value);
|
||||||
if (chan[c.chan].dacSample<0 || chan[c.chan].dacSample>=parent->song.sampleLen) {
|
if (chan[c.chan].dacSample<0 || chan[c.chan].dacSample>=parent->song.sampleLen) {
|
||||||
chan[c.chan].dacSample=-1;
|
chan[c.chan].dacSample=-1;
|
||||||
if (dumpWrites) addWrite(0xffff0002+(c.chan<<8),0);
|
if (dumpWrites) addWrite(0xffff0002+(c.chan<<8),0);
|
||||||
|
|
|
||||||
|
|
@ -559,7 +559,7 @@ int DivPlatformX1_010::dispatch(DivCommand c) {
|
||||||
if (chan[c.chan].furnacePCM) {
|
if (chan[c.chan].furnacePCM) {
|
||||||
chan[c.chan].pcm=true;
|
chan[c.chan].pcm=true;
|
||||||
chan[c.chan].macroInit(ins);
|
chan[c.chan].macroInit(ins);
|
||||||
chan[c.chan].sample=ins->amiga.initSample;
|
chan[c.chan].sample=ins->amiga.getSample(c.value);
|
||||||
if (chan[c.chan].sample>=0 && chan[c.chan].sample<parent->song.sampleLen) {
|
if (chan[c.chan].sample>=0 && chan[c.chan].sample<parent->song.sampleLen) {
|
||||||
DivSample* s=parent->getSample(chan[c.chan].sample);
|
DivSample* s=parent->getSample(chan[c.chan].sample);
|
||||||
chWrite(c.chan,4,(s->offX1_010>>12)&0xff);
|
chWrite(c.chan,4,(s->offX1_010>>12)&0xff);
|
||||||
|
|
|
||||||
|
|
@ -23,6 +23,7 @@
|
||||||
#include <string.h>
|
#include <string.h>
|
||||||
#include <math.h>
|
#include <math.h>
|
||||||
|
|
||||||
|
#include "sound/ymfm/ymfm_opn.h"
|
||||||
#include "ym2203shared.h"
|
#include "ym2203shared.h"
|
||||||
|
|
||||||
#include "fmshared_OPN.h"
|
#include "fmshared_OPN.h"
|
||||||
|
|
@ -51,7 +52,6 @@ const char* regCheatSheetYM2203[]={
|
||||||
"SSG_Control_Env", "00D",
|
"SSG_Control_Env", "00D",
|
||||||
// FM (Common)
|
// FM (Common)
|
||||||
"FM_Test", "021",
|
"FM_Test", "021",
|
||||||
"FM_LFOFreq", "022",
|
|
||||||
"ClockA1", "024",
|
"ClockA1", "024",
|
||||||
"ClockA2", "025",
|
"ClockA2", "025",
|
||||||
"ClockB", "026",
|
"ClockB", "026",
|
||||||
|
|
@ -157,9 +157,6 @@ const char* regCheatSheetYM2203[]={
|
||||||
"FM1_FB_ALG", "0B0",
|
"FM1_FB_ALG", "0B0",
|
||||||
"FM2_FB_ALG", "0B1",
|
"FM2_FB_ALG", "0B1",
|
||||||
"FM3_FB_ALG", "0B2",
|
"FM3_FB_ALG", "0B2",
|
||||||
"FM1_Pan_LFO", "0B4",
|
|
||||||
"FM2_Pan_LFO", "0B5",
|
|
||||||
"FM3_Pan_LFO", "0B6",
|
|
||||||
NULL
|
NULL
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
@ -169,9 +166,6 @@ const char** DivPlatformYM2203::getRegisterSheet() {
|
||||||
|
|
||||||
const char* DivPlatformYM2203::getEffectName(unsigned char effect) {
|
const char* DivPlatformYM2203::getEffectName(unsigned char effect) {
|
||||||
switch (effect) {
|
switch (effect) {
|
||||||
case 0x10:
|
|
||||||
return "10xy: Setup LFO (x: enable; y: speed)";
|
|
||||||
break;
|
|
||||||
case 0x11:
|
case 0x11:
|
||||||
return "11xx: Set feedback (0 to 7)";
|
return "11xx: Set feedback (0 to 7)";
|
||||||
break;
|
break;
|
||||||
|
|
@ -290,19 +284,12 @@ const char* DivPlatformYM2203::getEffectName(unsigned char effect) {
|
||||||
void DivPlatformYM2203::acquire(short* bufL, short* bufR, size_t start, size_t len) {
|
void DivPlatformYM2203::acquire(short* bufL, short* bufR, size_t start, size_t len) {
|
||||||
static int os;
|
static int os;
|
||||||
|
|
||||||
/*ymfm::ym2612::fm_engine* fme=fm->debug_fm_engine();
|
ymfm::ym2203::fm_engine* fme=fm->debug_fm_engine();
|
||||||
ymfm::ssg_engine* ssge=fm->debug_ssg_engine();
|
|
||||||
ymfm::adpcm_a_engine* aae=fm->debug_adpcm_a_engine();
|
|
||||||
ymfm::adpcm_b_engine* abe=fm->debug_adpcm_b_engine();
|
|
||||||
|
|
||||||
ymfm::ssg_engine::output_data ssgOut;
|
ymfm::fm_channel<ymfm::opn_registers_base<false>>* fmChan[3];
|
||||||
|
for (int i=0; i<3; i++) {
|
||||||
ymfm::fm_channel<ymfm::opn_registers_base<true>>* fmChan[6];
|
|
||||||
ymfm::adpcm_a_channel* adpcmAChan[6];
|
|
||||||
for (int i=0; i<6; i++) {
|
|
||||||
fmChan[i]=fme->debug_channel(i);
|
fmChan[i]=fme->debug_channel(i);
|
||||||
adpcmAChan[i]=aae->debug_channel(i);
|
}
|
||||||
}*/
|
|
||||||
|
|
||||||
for (size_t h=start; h<start+len; h++) {
|
for (size_t h=start; h<start+len; h++) {
|
||||||
os=0;
|
os=0;
|
||||||
|
|
@ -313,7 +300,7 @@ void DivPlatformYM2203::acquire(short* bufL, short* bufR, size_t start, size_t l
|
||||||
fm->write(0x1,w.val);
|
fm->write(0x1,w.val);
|
||||||
regPool[w.addr&0xff]=w.val;
|
regPool[w.addr&0xff]=w.val;
|
||||||
writes.pop();
|
writes.pop();
|
||||||
delay=16;
|
delay=6;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -325,22 +312,14 @@ void DivPlatformYM2203::acquire(short* bufL, short* bufR, size_t start, size_t l
|
||||||
|
|
||||||
bufL[h]=os;
|
bufL[h]=os;
|
||||||
|
|
||||||
/*
|
|
||||||
for (int i=0; i<6; i++) {
|
for (int i=0; i<3; i++) {
|
||||||
oscBuf[i]->data[oscBuf[i]->needle++]=(fmChan[i]->debug_output(0)+fmChan[i]->debug_output(1));
|
oscBuf[i]->data[oscBuf[i]->needle++]=(fmChan[i]->debug_output(0)+fmChan[i]->debug_output(1));
|
||||||
}
|
}
|
||||||
|
|
||||||
ssge->get_last_out(ssgOut);
|
for (int i=3; i<6; i++) {
|
||||||
for (int i=6; i<9; i++) {
|
oscBuf[i]->data[oscBuf[i]->needle++]=fmout.data[i-2];
|
||||||
oscBuf[i]->data[oscBuf[i]->needle++]=ssgOut.data[i-6];
|
|
||||||
}
|
}
|
||||||
|
|
||||||
for (int i=9; i<15; i++) {
|
|
||||||
oscBuf[i]->data[oscBuf[i]->needle++]=adpcmAChan[i-9]->get_last_out(0)+adpcmAChan[i-9]->get_last_out(1);
|
|
||||||
}
|
|
||||||
|
|
||||||
oscBuf[15]->data[oscBuf[15]->needle++]=abe->get_last_out(0)+abe->get_last_out(1);
|
|
||||||
*/
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -363,10 +342,14 @@ void DivPlatformYM2203::tick(bool sysTick) {
|
||||||
for (int j=0; j<4; j++) {
|
for (int j=0; j<4; j++) {
|
||||||
unsigned short baseAddr=chanOffs[i]|opOffs[j];
|
unsigned short baseAddr=chanOffs[i]|opOffs[j];
|
||||||
DivInstrumentFM::Operator& op=chan[i].state.op[j];
|
DivInstrumentFM::Operator& op=chan[i].state.op[j];
|
||||||
if (isOutput[chan[i].state.alg][j]) {
|
if (isMuted[i]) {
|
||||||
rWrite(baseAddr+ADDR_TL,127-(((127-op.tl)*(chan[i].outVol&0x7f))/127));
|
rWrite(baseAddr+ADDR_TL,127);
|
||||||
} else {
|
} else {
|
||||||
rWrite(baseAddr+ADDR_TL,op.tl);
|
if (isOutput[chan[i].state.alg][j]) {
|
||||||
|
rWrite(baseAddr+ADDR_TL,127-(((127-op.tl)*(chan[i].outVol&0x7f))/127));
|
||||||
|
} else {
|
||||||
|
rWrite(baseAddr+ADDR_TL,op.tl);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
@ -387,11 +370,6 @@ void DivPlatformYM2203::tick(bool sysTick) {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (chan[i].std.panL.had) {
|
|
||||||
chan[i].pan=chan[i].std.panL.val&3;
|
|
||||||
rWrite(chanOffs[i]+ADDR_LRAF,(isMuted[i]?0:(chan[i].pan<<6))|(chan[i].state.fms&7)|((chan[i].state.ams&3)<<4));
|
|
||||||
}
|
|
||||||
|
|
||||||
if (chan[i].std.pitch.had) {
|
if (chan[i].std.pitch.had) {
|
||||||
if (chan[i].std.pitch.mode) {
|
if (chan[i].std.pitch.mode) {
|
||||||
chan[i].pitch2+=chan[i].std.pitch.val;
|
chan[i].pitch2+=chan[i].std.pitch.val;
|
||||||
|
|
@ -429,14 +407,6 @@ void DivPlatformYM2203::tick(bool sysTick) {
|
||||||
chan[i].state.fb=chan[i].std.fb.val;
|
chan[i].state.fb=chan[i].std.fb.val;
|
||||||
rWrite(chanOffs[i]+ADDR_FB_ALG,(chan[i].state.alg&7)|(chan[i].state.fb<<3));
|
rWrite(chanOffs[i]+ADDR_FB_ALG,(chan[i].state.alg&7)|(chan[i].state.fb<<3));
|
||||||
}
|
}
|
||||||
if (chan[i].std.fms.had) {
|
|
||||||
chan[i].state.fms=chan[i].std.fms.val;
|
|
||||||
rWrite(chanOffs[i]+ADDR_LRAF,(isMuted[i]?0:(chan[i].pan<<6))|(chan[i].state.fms&7)|((chan[i].state.ams&3)<<4));
|
|
||||||
}
|
|
||||||
if (chan[i].std.ams.had) {
|
|
||||||
chan[i].state.ams=chan[i].std.ams.val;
|
|
||||||
rWrite(chanOffs[i]+ADDR_LRAF,(isMuted[i]?0:(chan[i].pan<<6))|(chan[i].state.fms&7)|((chan[i].state.ams&3)<<4));
|
|
||||||
}
|
|
||||||
for (int j=0; j<4; j++) {
|
for (int j=0; j<4; j++) {
|
||||||
unsigned short baseAddr=chanOffs[i]|opOffs[j];
|
unsigned short baseAddr=chanOffs[i]|opOffs[j];
|
||||||
DivInstrumentFM::Operator& op=chan[i].state.op[j];
|
DivInstrumentFM::Operator& op=chan[i].state.op[j];
|
||||||
|
|
@ -467,10 +437,14 @@ void DivPlatformYM2203::tick(bool sysTick) {
|
||||||
}
|
}
|
||||||
if (m.tl.had) {
|
if (m.tl.had) {
|
||||||
op.tl=127-m.tl.val;
|
op.tl=127-m.tl.val;
|
||||||
if (isOutput[chan[i].state.alg][j]) {
|
if (isMuted[i]) {
|
||||||
rWrite(baseAddr+ADDR_TL,127-(((127-op.tl)*(chan[i].outVol&0x7f))/127));
|
rWrite(baseAddr+ADDR_TL,127);
|
||||||
} else {
|
} else {
|
||||||
rWrite(baseAddr+ADDR_TL,op.tl);
|
if (isOutput[chan[i].state.alg][j]) {
|
||||||
|
rWrite(baseAddr+ADDR_TL,127-(((127-op.tl)*(chan[i].outVol&0x7f))/127));
|
||||||
|
} else {
|
||||||
|
rWrite(baseAddr+ADDR_TL,op.tl);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if (m.rs.had) {
|
if (m.rs.had) {
|
||||||
|
|
@ -574,13 +548,17 @@ int DivPlatformYM2203::dispatch(DivCommand c) {
|
||||||
for (int i=0; i<4; i++) {
|
for (int i=0; i<4; i++) {
|
||||||
unsigned short baseAddr=chanOffs[c.chan]|opOffs[i];
|
unsigned short baseAddr=chanOffs[c.chan]|opOffs[i];
|
||||||
DivInstrumentFM::Operator& op=chan[c.chan].state.op[i];
|
DivInstrumentFM::Operator& op=chan[c.chan].state.op[i];
|
||||||
if (isOutput[chan[c.chan].state.alg][i]) {
|
if (isMuted[c.chan]) {
|
||||||
if (!chan[c.chan].active || chan[c.chan].insChanged) {
|
rWrite(baseAddr+ADDR_TL,127);
|
||||||
rWrite(baseAddr+ADDR_TL,127-(((127-op.tl)*(chan[c.chan].outVol&0x7f))/127));
|
|
||||||
}
|
|
||||||
} else {
|
} else {
|
||||||
if (chan[c.chan].insChanged) {
|
if (isOutput[chan[c.chan].state.alg][i]) {
|
||||||
rWrite(baseAddr+ADDR_TL,op.tl);
|
if (!chan[c.chan].active || chan[c.chan].insChanged) {
|
||||||
|
rWrite(baseAddr+ADDR_TL,127-(((127-op.tl)*(chan[c.chan].outVol&0x7f))/127));
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
if (chan[c.chan].insChanged) {
|
||||||
|
rWrite(baseAddr+ADDR_TL,op.tl);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if (chan[c.chan].insChanged) {
|
if (chan[c.chan].insChanged) {
|
||||||
|
|
@ -594,7 +572,6 @@ int DivPlatformYM2203::dispatch(DivCommand c) {
|
||||||
}
|
}
|
||||||
if (chan[c.chan].insChanged) {
|
if (chan[c.chan].insChanged) {
|
||||||
rWrite(chanOffs[c.chan]+ADDR_FB_ALG,(chan[c.chan].state.alg&7)|(chan[c.chan].state.fb<<3));
|
rWrite(chanOffs[c.chan]+ADDR_FB_ALG,(chan[c.chan].state.alg&7)|(chan[c.chan].state.fb<<3));
|
||||||
rWrite(chanOffs[c.chan]+ADDR_LRAF,(isMuted[c.chan]?0:(chan[c.chan].pan<<6))|(chan[c.chan].state.fms&7)|((chan[c.chan].state.ams&3)<<4));
|
|
||||||
}
|
}
|
||||||
chan[c.chan].insChanged=false;
|
chan[c.chan].insChanged=false;
|
||||||
|
|
||||||
|
|
@ -631,10 +608,14 @@ int DivPlatformYM2203::dispatch(DivCommand c) {
|
||||||
for (int i=0; i<4; i++) {
|
for (int i=0; i<4; i++) {
|
||||||
unsigned short baseAddr=chanOffs[c.chan]|opOffs[i];
|
unsigned short baseAddr=chanOffs[c.chan]|opOffs[i];
|
||||||
DivInstrumentFM::Operator& op=chan[c.chan].state.op[i];
|
DivInstrumentFM::Operator& op=chan[c.chan].state.op[i];
|
||||||
if (isOutput[chan[c.chan].state.alg][i]) {
|
if (isMuted[c.chan]) {
|
||||||
rWrite(baseAddr+ADDR_TL,127-(((127-op.tl)*(chan[c.chan].outVol&0x7f))/127));
|
rWrite(baseAddr+ADDR_TL,127);
|
||||||
} else {
|
} else {
|
||||||
rWrite(baseAddr+ADDR_TL,op.tl);
|
if (isOutput[chan[c.chan].state.alg][i]) {
|
||||||
|
rWrite(baseAddr+ADDR_TL,127-(((127-op.tl)*(chan[c.chan].outVol&0x7f))/127));
|
||||||
|
} else {
|
||||||
|
rWrite(baseAddr+ADDR_TL,op.tl);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
|
|
@ -649,15 +630,6 @@ int DivPlatformYM2203::dispatch(DivCommand c) {
|
||||||
}
|
}
|
||||||
chan[c.chan].ins=c.value;
|
chan[c.chan].ins=c.value;
|
||||||
break;
|
break;
|
||||||
case DIV_CMD_PANNING: {
|
|
||||||
if (c.value==0 && c.value2==0) {
|
|
||||||
chan[c.chan].pan=3;
|
|
||||||
} else {
|
|
||||||
chan[c.chan].pan=(c.value2>0)|((c.value>0)<<1);
|
|
||||||
}
|
|
||||||
rWrite(chanOffs[c.chan]+ADDR_LRAF,(isMuted[c.chan]?0:(chan[c.chan].pan<<6))|(chan[c.chan].state.fms&7)|((chan[c.chan].state.ams&3)<<4));
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
case DIV_CMD_PITCH: {
|
case DIV_CMD_PITCH: {
|
||||||
chan[c.chan].pitch=c.value;
|
chan[c.chan].pitch=c.value;
|
||||||
chan[c.chan].freqChanged=true;
|
chan[c.chan].freqChanged=true;
|
||||||
|
|
@ -736,10 +708,6 @@ int DivPlatformYM2203::dispatch(DivCommand c) {
|
||||||
chan[c.chan].freqChanged=true;
|
chan[c.chan].freqChanged=true;
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
case DIV_CMD_FM_LFO: {
|
|
||||||
rWrite(0x22,(c.value&7)|((c.value>>4)<<3));
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
case DIV_CMD_FM_FB: {
|
case DIV_CMD_FM_FB: {
|
||||||
if (c.chan>2) break;
|
if (c.chan>2) break;
|
||||||
chan[c.chan].state.fb=c.value&7;
|
chan[c.chan].state.fb=c.value&7;
|
||||||
|
|
@ -759,10 +727,14 @@ int DivPlatformYM2203::dispatch(DivCommand c) {
|
||||||
unsigned short baseAddr=chanOffs[c.chan]|opOffs[orderedOps[c.value]];
|
unsigned short baseAddr=chanOffs[c.chan]|opOffs[orderedOps[c.value]];
|
||||||
DivInstrumentFM::Operator& op=chan[c.chan].state.op[orderedOps[c.value]];
|
DivInstrumentFM::Operator& op=chan[c.chan].state.op[orderedOps[c.value]];
|
||||||
op.tl=c.value2;
|
op.tl=c.value2;
|
||||||
if (isOutput[chan[c.chan].state.alg][c.value]) {
|
if (isMuted[c.chan]) {
|
||||||
rWrite(baseAddr+ADDR_TL,127-(((127-op.tl)*(chan[c.chan].outVol&0x7f))/127));
|
rWrite(baseAddr+ADDR_TL,127);
|
||||||
} else {
|
} else {
|
||||||
rWrite(baseAddr+ADDR_TL,op.tl);
|
if (isOutput[chan[c.chan].state.alg][c.value]) {
|
||||||
|
rWrite(baseAddr+ADDR_TL,127-(((127-op.tl)*(chan[c.chan].outVol&0x7f))/127));
|
||||||
|
} else {
|
||||||
|
rWrite(baseAddr+ADDR_TL,op.tl);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
@ -944,8 +916,19 @@ void DivPlatformYM2203::muteChannel(int ch, bool mute) {
|
||||||
ay->muteChannel(ch-3,mute);
|
ay->muteChannel(ch-3,mute);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
// FM
|
for (int j=0; j<4; j++) {
|
||||||
rWrite(chanOffs[ch]+ADDR_LRAF,(isMuted[ch]?0:(chan[ch].pan<<6))|(chan[ch].state.fms&7)|((chan[ch].state.ams&3)<<4));
|
unsigned short baseAddr=chanOffs[ch]|opOffs[j];
|
||||||
|
DivInstrumentFM::Operator& op=chan[ch].state.op[j];
|
||||||
|
if (isMuted[ch]) {
|
||||||
|
rWrite(baseAddr+ADDR_TL,127);
|
||||||
|
} else {
|
||||||
|
if (isOutput[chan[ch].state.alg][j]) {
|
||||||
|
rWrite(baseAddr+ADDR_TL,127-(((127-op.tl)*(chan[ch].outVol&0x7f))/127));
|
||||||
|
} else {
|
||||||
|
rWrite(baseAddr+ADDR_TL,op.tl);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void DivPlatformYM2203::forceIns() {
|
void DivPlatformYM2203::forceIns() {
|
||||||
|
|
@ -953,10 +936,14 @@ void DivPlatformYM2203::forceIns() {
|
||||||
for (int j=0; j<4; j++) {
|
for (int j=0; j<4; j++) {
|
||||||
unsigned short baseAddr=chanOffs[i]|opOffs[j];
|
unsigned short baseAddr=chanOffs[i]|opOffs[j];
|
||||||
DivInstrumentFM::Operator& op=chan[i].state.op[j];
|
DivInstrumentFM::Operator& op=chan[i].state.op[j];
|
||||||
if (isOutput[chan[i].state.alg][j]) {
|
if (isMuted[i]) {
|
||||||
rWrite(baseAddr+ADDR_TL,127-(((127-op.tl)*(chan[i].outVol&0x7f))/127));
|
rWrite(baseAddr+ADDR_TL,127);
|
||||||
} else {
|
} else {
|
||||||
rWrite(baseAddr+ADDR_TL,op.tl);
|
if (isOutput[chan[i].state.alg][j]) {
|
||||||
|
rWrite(baseAddr+ADDR_TL,127-(((127-op.tl)*(chan[i].outVol&0x7f))/127));
|
||||||
|
} else {
|
||||||
|
rWrite(baseAddr+ADDR_TL,op.tl);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
rWrite(baseAddr+ADDR_MULT_DT,(op.mult&15)|(dtTable[op.dt&7]<<4));
|
rWrite(baseAddr+ADDR_MULT_DT,(op.mult&15)|(dtTable[op.dt&7]<<4));
|
||||||
rWrite(baseAddr+ADDR_RS_AR,(op.ar&31)|(op.rs<<6));
|
rWrite(baseAddr+ADDR_RS_AR,(op.ar&31)|(op.rs<<6));
|
||||||
|
|
@ -966,7 +953,6 @@ void DivPlatformYM2203::forceIns() {
|
||||||
rWrite(baseAddr+ADDR_SSG,op.ssgEnv&15);
|
rWrite(baseAddr+ADDR_SSG,op.ssgEnv&15);
|
||||||
}
|
}
|
||||||
rWrite(chanOffs[i]+ADDR_FB_ALG,(chan[i].state.alg&7)|(chan[i].state.fb<<3));
|
rWrite(chanOffs[i]+ADDR_FB_ALG,(chan[i].state.alg&7)|(chan[i].state.fb<<3));
|
||||||
rWrite(chanOffs[i]+ADDR_LRAF,(isMuted[i]?0:(chan[i].pan<<6))|(chan[i].state.fms&7)|((chan[i].state.ams&3)<<4));
|
|
||||||
if (chan[i].active) {
|
if (chan[i].active) {
|
||||||
chan[i].keyOn=true;
|
chan[i].keyOn=true;
|
||||||
chan[i].freqChanged=true;
|
chan[i].freqChanged=true;
|
||||||
|
|
@ -1039,9 +1025,6 @@ void DivPlatformYM2203::reset() {
|
||||||
|
|
||||||
extMode=false;
|
extMode=false;
|
||||||
|
|
||||||
// LFO
|
|
||||||
immWrite(0x22,0x08);
|
|
||||||
|
|
||||||
ay->reset();
|
ay->reset();
|
||||||
ay->getRegisterWrites().clear();
|
ay->getRegisterWrites().clear();
|
||||||
ay->flushWrites();
|
ay->flushWrites();
|
||||||
|
|
@ -1104,6 +1087,7 @@ int DivPlatformYM2203::init(DivEngine* p, int channels, int sugRate, unsigned in
|
||||||
oscBuf[i]=new DivDispatchOscBuffer;
|
oscBuf[i]=new DivDispatchOscBuffer;
|
||||||
}
|
}
|
||||||
fm=new ymfm::ym2203(iface);
|
fm=new ymfm::ym2203(iface);
|
||||||
|
fm->set_fidelity(ymfm::OPN_FIDELITY_MIN);
|
||||||
// YM2149, 2MHz
|
// YM2149, 2MHz
|
||||||
ay=new DivPlatformAY8910;
|
ay=new DivPlatformAY8910;
|
||||||
ay->init(p,3,sugRate,35);
|
ay->init(p,3,sugRate,35);
|
||||||
|
|
|
||||||
|
|
@ -45,7 +45,6 @@ class DivPlatformYM2203: public DivDispatch {
|
||||||
bool active, insChanged, freqChanged, keyOn, keyOff, portaPause, inPorta, furnacePCM, hardReset;
|
bool active, insChanged, freqChanged, keyOn, keyOff, portaPause, inPorta, furnacePCM, hardReset;
|
||||||
int vol, outVol;
|
int vol, outVol;
|
||||||
int sample;
|
int sample;
|
||||||
unsigned char pan;
|
|
||||||
DivMacroInt std;
|
DivMacroInt std;
|
||||||
void macroInit(DivInstrument* which) {
|
void macroInit(DivInstrument* which) {
|
||||||
std.init(which);
|
std.init(which);
|
||||||
|
|
@ -75,8 +74,7 @@ class DivPlatformYM2203: public DivDispatch {
|
||||||
hardReset(false),
|
hardReset(false),
|
||||||
vol(0),
|
vol(0),
|
||||||
outVol(15),
|
outVol(15),
|
||||||
sample(-1),
|
sample(-1) {}
|
||||||
pan(3) {}
|
|
||||||
};
|
};
|
||||||
Channel chan[6];
|
Channel chan[6];
|
||||||
DivDispatchOscBuffer* oscBuf[6];
|
DivDispatchOscBuffer* oscBuf[6];
|
||||||
|
|
|
||||||
574
src/engine/platform/ym2203ext.cpp
Normal file
574
src/engine/platform/ym2203ext.cpp
Normal file
|
|
@ -0,0 +1,574 @@
|
||||||
|
/**
|
||||||
|
* Furnace Tracker - multi-system chiptune tracker
|
||||||
|
* Copyright (C) 2021-2022 tildearrow and contributors
|
||||||
|
*
|
||||||
|
* This program is free software; you can redistribute it and/or modify
|
||||||
|
* it under the terms of the GNU General Public License as published by
|
||||||
|
* the Free Software Foundation; either version 2 of the License, or
|
||||||
|
* (at your option) any later version.
|
||||||
|
*
|
||||||
|
* This program is distributed in the hope that it will be useful,
|
||||||
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
|
* GNU General Public License for more details.
|
||||||
|
*
|
||||||
|
* You should have received a copy of the GNU General Public License along
|
||||||
|
* with this program; if not, write to the Free Software Foundation, Inc.,
|
||||||
|
* 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include "ym2610bext.h"
|
||||||
|
#include "../engine.h"
|
||||||
|
#include <math.h>
|
||||||
|
|
||||||
|
#include "ym2610shared.h"
|
||||||
|
#include "fmshared_OPN.h"
|
||||||
|
|
||||||
|
int DivPlatformYM2610BExt::dispatch(DivCommand c) {
|
||||||
|
if (c.chan<2) {
|
||||||
|
return DivPlatformYM2610B::dispatch(c);
|
||||||
|
}
|
||||||
|
if (c.chan>5) {
|
||||||
|
c.chan-=3;
|
||||||
|
return DivPlatformYM2610B::dispatch(c);
|
||||||
|
}
|
||||||
|
int ch=c.chan-2;
|
||||||
|
int ordch=orderedOps[ch];
|
||||||
|
switch (c.cmd) {
|
||||||
|
case DIV_CMD_NOTE_ON: {
|
||||||
|
DivInstrument* ins=parent->getIns(opChan[ch].ins,DIV_INS_FM);
|
||||||
|
|
||||||
|
unsigned short baseAddr=chanOffs[2]|opOffs[ordch];
|
||||||
|
DivInstrumentFM::Operator op=ins->fm.op[ordch];
|
||||||
|
// TODO: how does this work?!
|
||||||
|
if (isOpMuted[ch]) {
|
||||||
|
rWrite(baseAddr+0x40,127);
|
||||||
|
} else {
|
||||||
|
if (opChan[ch].insChanged) {
|
||||||
|
rWrite(baseAddr+0x40,127-(((127-op.tl)*(opChan[ch].vol&0x7f))/127));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (opChan[ch].insChanged) {
|
||||||
|
rWrite(baseAddr+0x30,(op.mult&15)|(dtTable[op.dt&7]<<4));
|
||||||
|
rWrite(baseAddr+0x50,(op.ar&31)|(op.rs<<6));
|
||||||
|
rWrite(baseAddr+0x60,(op.dr&31)|(op.am<<7));
|
||||||
|
rWrite(baseAddr+0x70,op.d2r&31);
|
||||||
|
rWrite(baseAddr+0x80,(op.rr&15)|(op.sl<<4));
|
||||||
|
rWrite(baseAddr+0x90,op.ssgEnv&15);
|
||||||
|
}
|
||||||
|
if (opChan[ch].insChanged) { // TODO how does this work?
|
||||||
|
rWrite(chanOffs[2]+0xb0,(ins->fm.alg&7)|(ins->fm.fb<<3));
|
||||||
|
rWrite(chanOffs[2]+0xb4,(opChan[ch].pan<<6)|(ins->fm.fms&7)|((ins->fm.ams&3)<<4));
|
||||||
|
}
|
||||||
|
opChan[ch].insChanged=false;
|
||||||
|
|
||||||
|
if (c.value!=DIV_NOTE_NULL) {
|
||||||
|
opChan[ch].baseFreq=NOTE_FREQUENCY(c.value);
|
||||||
|
opChan[ch].portaPause=false;
|
||||||
|
opChan[ch].freqChanged=true;
|
||||||
|
}
|
||||||
|
opChan[ch].keyOn=true;
|
||||||
|
opChan[ch].active=true;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
case DIV_CMD_NOTE_OFF:
|
||||||
|
opChan[ch].keyOff=true;
|
||||||
|
opChan[ch].keyOn=false;
|
||||||
|
opChan[ch].active=false;
|
||||||
|
break;
|
||||||
|
case DIV_CMD_VOLUME: {
|
||||||
|
opChan[ch].vol=c.value;
|
||||||
|
DivInstrument* ins=parent->getIns(opChan[ch].ins,DIV_INS_FM);
|
||||||
|
unsigned short baseAddr=chanOffs[2]|opOffs[ordch];
|
||||||
|
DivInstrumentFM::Operator op=ins->fm.op[ordch];
|
||||||
|
if (isOpMuted[ch]) {
|
||||||
|
rWrite(baseAddr+0x40,127);
|
||||||
|
} else {
|
||||||
|
rWrite(baseAddr+0x40,127-(((127-op.tl)*(opChan[ch].vol&0x7f))/127));
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
case DIV_CMD_GET_VOLUME: {
|
||||||
|
return opChan[ch].vol;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
case DIV_CMD_INSTRUMENT:
|
||||||
|
if (opChan[ch].ins!=c.value || c.value2==1) {
|
||||||
|
opChan[ch].insChanged=true;
|
||||||
|
}
|
||||||
|
opChan[ch].ins=c.value;
|
||||||
|
break;
|
||||||
|
case DIV_CMD_PANNING: {
|
||||||
|
if (c.value==0 && c.value2==0) {
|
||||||
|
opChan[ch].pan=3;
|
||||||
|
} else {
|
||||||
|
opChan[ch].pan=(c.value2>0)|((c.value>0)<<1);
|
||||||
|
}
|
||||||
|
DivInstrument* ins=parent->getIns(opChan[ch].ins,DIV_INS_FM);
|
||||||
|
if (parent->song.sharedExtStat) {
|
||||||
|
for (int i=0; i<4; i++) {
|
||||||
|
if (ch==i) continue;
|
||||||
|
opChan[i].pan=opChan[ch].pan;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
rWrite(chanOffs[2]+0xb4,(opChan[ch].pan<<6)|(ins->fm.fms&7)|((ins->fm.ams&3)<<4));
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
case DIV_CMD_PITCH: {
|
||||||
|
opChan[ch].pitch=c.value;
|
||||||
|
opChan[ch].freqChanged=true;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
case DIV_CMD_NOTE_PORTA: {
|
||||||
|
if (parent->song.linearPitch==2) {
|
||||||
|
int destFreq=NOTE_FREQUENCY(c.value2);
|
||||||
|
bool return2=false;
|
||||||
|
if (destFreq>opChan[ch].baseFreq) {
|
||||||
|
opChan[ch].baseFreq+=c.value;
|
||||||
|
if (opChan[ch].baseFreq>=destFreq) {
|
||||||
|
opChan[ch].baseFreq=destFreq;
|
||||||
|
return2=true;
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
opChan[ch].baseFreq-=c.value;
|
||||||
|
if (opChan[ch].baseFreq<=destFreq) {
|
||||||
|
opChan[ch].baseFreq=destFreq;
|
||||||
|
return2=true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
opChan[ch].freqChanged=true;
|
||||||
|
if (return2) {
|
||||||
|
//opChan[ch].inPorta=false;
|
||||||
|
return 2;
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
int boundaryBottom=parent->calcBaseFreq(chipClock,CHIP_FREQBASE,0,false);
|
||||||
|
int boundaryTop=parent->calcBaseFreq(chipClock,CHIP_FREQBASE,12,false);
|
||||||
|
int destFreq=NOTE_FNUM_BLOCK(c.value2,11);
|
||||||
|
int newFreq;
|
||||||
|
bool return2=false;
|
||||||
|
if (opChan[ch].portaPause) {
|
||||||
|
opChan[ch].baseFreq=opChan[ch].portaPauseFreq;
|
||||||
|
}
|
||||||
|
if (destFreq>opChan[ch].baseFreq) {
|
||||||
|
newFreq=opChan[ch].baseFreq+c.value;
|
||||||
|
if (newFreq>=destFreq) {
|
||||||
|
newFreq=destFreq;
|
||||||
|
return2=true;
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
newFreq=opChan[ch].baseFreq-c.value;
|
||||||
|
if (newFreq<=destFreq) {
|
||||||
|
newFreq=destFreq;
|
||||||
|
return2=true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
// what the heck!
|
||||||
|
if (!opChan[ch].portaPause) {
|
||||||
|
if ((newFreq&0x7ff)>boundaryTop && (newFreq&0xf800)<0x3800) {
|
||||||
|
if (parent->song.fbPortaPause) {
|
||||||
|
opChan[ch].portaPauseFreq=(boundaryBottom)|((newFreq+0x800)&0xf800);
|
||||||
|
opChan[ch].portaPause=true;
|
||||||
|
break;
|
||||||
|
} else {
|
||||||
|
newFreq=(newFreq>>1)|((newFreq+0x800)&0xf800);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if ((newFreq&0x7ff)<boundaryBottom && (newFreq&0xf800)>0) {
|
||||||
|
if (parent->song.fbPortaPause) {
|
||||||
|
opChan[ch].portaPauseFreq=newFreq=(boundaryTop-1)|((newFreq-0x800)&0xf800);
|
||||||
|
opChan[ch].portaPause=true;
|
||||||
|
break;
|
||||||
|
} else {
|
||||||
|
newFreq=(newFreq<<1)|((newFreq-0x800)&0xf800);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
opChan[ch].portaPause=false;
|
||||||
|
opChan[ch].freqChanged=true;
|
||||||
|
opChan[ch].baseFreq=newFreq;
|
||||||
|
if (return2) return 2;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
case DIV_CMD_LEGATO: {
|
||||||
|
opChan[ch].baseFreq=NOTE_FREQUENCY(c.value);
|
||||||
|
opChan[ch].freqChanged=true;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
case DIV_CMD_FM_LFO: {
|
||||||
|
rWrite(0x22,(c.value&7)|((c.value>>4)<<3));
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
case DIV_CMD_FM_MULT: { // TODO
|
||||||
|
unsigned short baseAddr=chanOffs[2]|opOffs[orderedOps[c.value]];
|
||||||
|
DivInstrument* ins=parent->getIns(opChan[ch].ins,DIV_INS_FM);
|
||||||
|
DivInstrumentFM::Operator op=ins->fm.op[orderedOps[c.value]];
|
||||||
|
rWrite(baseAddr+0x30,(c.value2&15)|(dtTable[op.dt&7]<<4));
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
case DIV_CMD_FM_TL: { // TODO
|
||||||
|
unsigned short baseAddr=chanOffs[2]|opOffs[orderedOps[c.value]];
|
||||||
|
DivInstrument* ins=parent->getIns(opChan[ch].ins,DIV_INS_FM);
|
||||||
|
if (isOutput[ins->fm.alg][c.value]) {
|
||||||
|
rWrite(baseAddr+0x40,127-(((127-c.value2)*(opChan[ch].vol&0x7f))/127));
|
||||||
|
} else {
|
||||||
|
rWrite(baseAddr+0x40,c.value2);
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
case DIV_CMD_FM_AR: {
|
||||||
|
if (c.value<0) {
|
||||||
|
for (int i=0; i<4; i++) {
|
||||||
|
DivInstrumentFM::Operator& op=chan[2].state.op[i];
|
||||||
|
op.ar=c.value2&31;
|
||||||
|
unsigned short baseAddr=chanOffs[2]|opOffs[i];
|
||||||
|
rWrite(baseAddr+0x50,(op.ar&31)|(op.rs<<6));
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
DivInstrumentFM::Operator& op=chan[2].state.op[orderedOps[c.value]];
|
||||||
|
op.ar=c.value2&31;
|
||||||
|
unsigned short baseAddr=chanOffs[2]|opOffs[orderedOps[c.value]];
|
||||||
|
rWrite(baseAddr+0x50,(op.ar&31)|(op.rs<<6));
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
case DIV_CMD_FM_RS: {
|
||||||
|
if (c.value<0) {
|
||||||
|
for (int i=0; i<4; i++) {
|
||||||
|
DivInstrumentFM::Operator& op=chan[2].state.op[i];
|
||||||
|
op.rs=c.value2&3;
|
||||||
|
unsigned short baseAddr=chanOffs[2]|opOffs[i];
|
||||||
|
rWrite(baseAddr+ADDR_RS_AR,(op.ar&31)|(op.rs<<6));
|
||||||
|
}
|
||||||
|
} else if (c.value<4) {
|
||||||
|
DivInstrumentFM::Operator& op=chan[2].state.op[orderedOps[c.value]];
|
||||||
|
op.rs=c.value2&3;
|
||||||
|
unsigned short baseAddr=chanOffs[2]|opOffs[orderedOps[c.value]];
|
||||||
|
rWrite(baseAddr+ADDR_RS_AR,(op.ar&31)|(op.rs<<6));
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
case DIV_CMD_FM_AM: {
|
||||||
|
if (c.value<0) {
|
||||||
|
for (int i=0; i<4; i++) {
|
||||||
|
DivInstrumentFM::Operator& op=chan[2].state.op[i];
|
||||||
|
op.am=c.value2&1;
|
||||||
|
unsigned short baseAddr=chanOffs[2]|opOffs[i];
|
||||||
|
rWrite(baseAddr+ADDR_AM_DR,(op.dr&31)|(op.am<<7));
|
||||||
|
}
|
||||||
|
} else if (c.value<4) {
|
||||||
|
DivInstrumentFM::Operator& op=chan[2].state.op[orderedOps[c.value]];
|
||||||
|
op.am=c.value2&1;
|
||||||
|
unsigned short baseAddr=chanOffs[2]|opOffs[orderedOps[c.value]];
|
||||||
|
rWrite(baseAddr+ADDR_AM_DR,(op.dr&31)|(op.am<<7));
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
case DIV_CMD_FM_DR: {
|
||||||
|
if (c.value<0) {
|
||||||
|
for (int i=0; i<4; i++) {
|
||||||
|
DivInstrumentFM::Operator& op=chan[2].state.op[i];
|
||||||
|
op.dr=c.value2&31;
|
||||||
|
unsigned short baseAddr=chanOffs[2]|opOffs[i];
|
||||||
|
rWrite(baseAddr+ADDR_AM_DR,(op.dr&31)|(op.am<<7));
|
||||||
|
}
|
||||||
|
} else if (c.value<4) {
|
||||||
|
DivInstrumentFM::Operator& op=chan[2].state.op[orderedOps[c.value]];
|
||||||
|
op.dr=c.value2&31;
|
||||||
|
unsigned short baseAddr=chanOffs[2]|opOffs[orderedOps[c.value]];
|
||||||
|
rWrite(baseAddr+ADDR_AM_DR,(op.dr&31)|(op.am<<7));
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
case DIV_CMD_FM_SL: {
|
||||||
|
if (c.value<0) {
|
||||||
|
for (int i=0; i<4; i++) {
|
||||||
|
DivInstrumentFM::Operator& op=chan[2].state.op[i];
|
||||||
|
op.sl=c.value2&15;
|
||||||
|
unsigned short baseAddr=chanOffs[2]|opOffs[i];
|
||||||
|
rWrite(baseAddr+ADDR_SL_RR,(op.rr&15)|(op.sl<<4));
|
||||||
|
}
|
||||||
|
} else if (c.value<4) {
|
||||||
|
DivInstrumentFM::Operator& op=chan[2].state.op[orderedOps[c.value]];
|
||||||
|
op.sl=c.value2&15;
|
||||||
|
unsigned short baseAddr=chanOffs[2]|opOffs[orderedOps[c.value]];
|
||||||
|
rWrite(baseAddr+ADDR_SL_RR,(op.rr&15)|(op.sl<<4));
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
case DIV_CMD_FM_RR: {
|
||||||
|
if (c.value<0) {
|
||||||
|
for (int i=0; i<4; i++) {
|
||||||
|
DivInstrumentFM::Operator& op=chan[2].state.op[i];
|
||||||
|
op.rr=c.value2&15;
|
||||||
|
unsigned short baseAddr=chanOffs[2]|opOffs[i];
|
||||||
|
rWrite(baseAddr+ADDR_SL_RR,(op.rr&15)|(op.sl<<4));
|
||||||
|
}
|
||||||
|
} else if (c.value<4) {
|
||||||
|
DivInstrumentFM::Operator& op=chan[2].state.op[orderedOps[c.value]];
|
||||||
|
op.rr=c.value2&15;
|
||||||
|
unsigned short baseAddr=chanOffs[2]|opOffs[orderedOps[c.value]];
|
||||||
|
rWrite(baseAddr+ADDR_SL_RR,(op.rr&15)|(op.sl<<4));
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
case DIV_CMD_FM_D2R: {
|
||||||
|
if (c.value<0) {
|
||||||
|
for (int i=0; i<4; i++) {
|
||||||
|
DivInstrumentFM::Operator& op=chan[2].state.op[i];
|
||||||
|
op.d2r=c.value2&31;
|
||||||
|
unsigned short baseAddr=chanOffs[2]|opOffs[i];
|
||||||
|
rWrite(baseAddr+ADDR_DT2_D2R,op.d2r&31);
|
||||||
|
}
|
||||||
|
} else if (c.value<4) {
|
||||||
|
DivInstrumentFM::Operator& op=chan[2].state.op[orderedOps[c.value]];
|
||||||
|
op.d2r=c.value2&31;
|
||||||
|
unsigned short baseAddr=chanOffs[2]|opOffs[orderedOps[c.value]];
|
||||||
|
rWrite(baseAddr+ADDR_DT2_D2R,op.d2r&31);
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
case DIV_CMD_FM_DT: {
|
||||||
|
if (c.value<0) {
|
||||||
|
for (int i=0; i<4; i++) {
|
||||||
|
DivInstrumentFM::Operator& op=chan[2].state.op[i];
|
||||||
|
op.dt=c.value&7;
|
||||||
|
unsigned short baseAddr=chanOffs[2]|opOffs[i];
|
||||||
|
rWrite(baseAddr+ADDR_MULT_DT,(op.mult&15)|(dtTable[op.dt&7]<<4));
|
||||||
|
}
|
||||||
|
} else if (c.value<4) {
|
||||||
|
DivInstrumentFM::Operator& op=chan[2].state.op[orderedOps[c.value]];
|
||||||
|
op.dt=c.value2&7;
|
||||||
|
unsigned short baseAddr=chanOffs[2]|opOffs[orderedOps[c.value]];
|
||||||
|
rWrite(baseAddr+ADDR_MULT_DT,(op.mult&15)|(dtTable[op.dt&7]<<4));
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
case DIV_CMD_FM_SSG: {
|
||||||
|
if (c.value<0) {
|
||||||
|
for (int i=0; i<4; i++) {
|
||||||
|
DivInstrumentFM::Operator& op=chan[2].state.op[i];
|
||||||
|
op.ssgEnv=8^(c.value2&15);
|
||||||
|
unsigned short baseAddr=chanOffs[2]|opOffs[i];
|
||||||
|
rWrite(baseAddr+ADDR_SSG,op.ssgEnv&15);
|
||||||
|
}
|
||||||
|
} else if (c.value<4) {
|
||||||
|
DivInstrumentFM::Operator& op=chan[2].state.op[orderedOps[c.value]];
|
||||||
|
op.ssgEnv=8^(c.value2&15);
|
||||||
|
unsigned short baseAddr=chanOffs[2]|opOffs[orderedOps[c.value]];
|
||||||
|
rWrite(baseAddr+ADDR_SSG,op.ssgEnv&15);
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
case DIV_CMD_GET_VOLMAX:
|
||||||
|
return 127;
|
||||||
|
break;
|
||||||
|
case DIV_ALWAYS_SET_VOLUME:
|
||||||
|
return 0;
|
||||||
|
break;
|
||||||
|
case DIV_CMD_PRE_PORTA:
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
//printf("WARNING: unimplemented command %d\n",c.cmd);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
static int opChanOffsL[4]={
|
||||||
|
0xa9, 0xaa, 0xa8, 0xa2
|
||||||
|
};
|
||||||
|
|
||||||
|
static int opChanOffsH[4]={
|
||||||
|
0xad, 0xae, 0xac, 0xa6
|
||||||
|
};
|
||||||
|
|
||||||
|
void DivPlatformYM2610BExt::tick(bool sysTick) {
|
||||||
|
if (extMode) {
|
||||||
|
bool writeSomething=false;
|
||||||
|
unsigned char writeMask=2;
|
||||||
|
for (int i=0; i<4; i++) {
|
||||||
|
writeMask|=opChan[i].active<<(4+i);
|
||||||
|
if (opChan[i].keyOn || opChan[i].keyOff) {
|
||||||
|
writeSomething=true;
|
||||||
|
writeMask&=~(1<<(4+i));
|
||||||
|
opChan[i].keyOff=false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (writeSomething) {
|
||||||
|
immWrite(0x28,writeMask);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
DivPlatformYM2610B::tick(sysTick);
|
||||||
|
|
||||||
|
bool writeNoteOn=false;
|
||||||
|
unsigned char writeMask=2;
|
||||||
|
if (extMode) for (int i=0; i<4; i++) {
|
||||||
|
if (opChan[i].freqChanged) {
|
||||||
|
if (parent->song.linearPitch==2) {
|
||||||
|
opChan[i].freq=parent->calcFreq(opChan[i].baseFreq,opChan[i].pitch,false,4,opChan[i].pitch2,chipClock,CHIP_FREQBASE,11);
|
||||||
|
} else {
|
||||||
|
int fNum=parent->calcFreq(opChan[i].baseFreq&0x7ff,opChan[i].pitch,false,4,opChan[i].pitch2);
|
||||||
|
int block=(opChan[i].baseFreq&0xf800)>>11;
|
||||||
|
if (fNum<0) fNum=0;
|
||||||
|
if (fNum>2047) {
|
||||||
|
while (block<7) {
|
||||||
|
fNum>>=1;
|
||||||
|
block++;
|
||||||
|
}
|
||||||
|
if (fNum>2047) fNum=2047;
|
||||||
|
}
|
||||||
|
opChan[i].freq=(block<<11)|fNum;
|
||||||
|
}
|
||||||
|
if (opChan[i].freq>0x3fff) opChan[i].freq=0x3fff;
|
||||||
|
immWrite(opChanOffsH[i],opChan[i].freq>>8);
|
||||||
|
immWrite(opChanOffsL[i],opChan[i].freq&0xff);
|
||||||
|
}
|
||||||
|
writeMask|=opChan[i].active<<(4+i);
|
||||||
|
if (opChan[i].keyOn) {
|
||||||
|
writeNoteOn=true;
|
||||||
|
writeMask|=1<<(4+i);
|
||||||
|
opChan[i].keyOn=false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (writeNoteOn) {
|
||||||
|
immWrite(0x28,writeMask);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void DivPlatformYM2610BExt::muteChannel(int ch, bool mute) {
|
||||||
|
if (ch<2) {
|
||||||
|
DivPlatformYM2610B::muteChannel(ch,mute);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
if (ch>5) {
|
||||||
|
DivPlatformYM2610B::muteChannel(ch-3,mute);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
isOpMuted[ch-2]=mute;
|
||||||
|
|
||||||
|
int ordch=orderedOps[ch-2];
|
||||||
|
DivInstrument* ins=parent->getIns(opChan[ch-2].ins,DIV_INS_FM);
|
||||||
|
unsigned short baseAddr=chanOffs[2]|opOffs[ordch];
|
||||||
|
DivInstrumentFM::Operator op=ins->fm.op[ordch];
|
||||||
|
if (isOpMuted[ch-2]) {
|
||||||
|
rWrite(baseAddr+0x40,127);
|
||||||
|
} else if (isOutput[ins->fm.alg][ordch]) {
|
||||||
|
rWrite(baseAddr+0x40,127-(((127-op.tl)*(opChan[ch-2].vol&0x7f))/127));
|
||||||
|
} else {
|
||||||
|
rWrite(baseAddr+0x40,op.tl);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void DivPlatformYM2610BExt::forceIns() {
|
||||||
|
for (int i=0; i<6; i++) {
|
||||||
|
for (int j=0; j<4; j++) {
|
||||||
|
unsigned short baseAddr=chanOffs[i]|opOffs[j];
|
||||||
|
DivInstrumentFM::Operator& op=chan[i].state.op[j];
|
||||||
|
if (i==2) { // extended channel
|
||||||
|
if (isOpMuted[j]) {
|
||||||
|
rWrite(baseAddr+0x40,127);
|
||||||
|
} else if (isOutput[chan[i].state.alg][j]) {
|
||||||
|
rWrite(baseAddr+0x40,127-(((127-op.tl)*(opChan[j].vol&0x7f))/127));
|
||||||
|
} else {
|
||||||
|
rWrite(baseAddr+0x40,op.tl);
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
if (isMuted[i]) {
|
||||||
|
rWrite(baseAddr+ADDR_TL,127);
|
||||||
|
} else {
|
||||||
|
if (isOutput[chan[i].state.alg][j]) {
|
||||||
|
rWrite(baseAddr+ADDR_TL,127-(((127-op.tl)*(chan[i].outVol&0x7f))/127));
|
||||||
|
} else {
|
||||||
|
rWrite(baseAddr+ADDR_TL,op.tl);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
rWrite(baseAddr+ADDR_MULT_DT,(op.mult&15)|(dtTable[op.dt&7]<<4));
|
||||||
|
rWrite(baseAddr+ADDR_RS_AR,(op.ar&31)|(op.rs<<6));
|
||||||
|
rWrite(baseAddr+ADDR_AM_DR,(op.dr&31)|(op.am<<7));
|
||||||
|
rWrite(baseAddr+ADDR_DT2_D2R,op.d2r&31);
|
||||||
|
rWrite(baseAddr+ADDR_SL_RR,(op.rr&15)|(op.sl<<4));
|
||||||
|
rWrite(baseAddr+ADDR_SSG,op.ssgEnv&15);
|
||||||
|
}
|
||||||
|
rWrite(chanOffs[i]+ADDR_FB_ALG,(chan[i].state.alg&7)|(chan[i].state.fb<<3));
|
||||||
|
rWrite(chanOffs[i]+ADDR_LRAF,(isMuted[i]?0:(chan[i].pan<<6))|(chan[i].state.fms&7)|((chan[i].state.ams&3)<<4));
|
||||||
|
if (chan[i].active) {
|
||||||
|
chan[i].keyOn=true;
|
||||||
|
chan[i].freqChanged=true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
for (int i=6; i<16; i++) {
|
||||||
|
chan[i].insChanged=true;
|
||||||
|
}
|
||||||
|
ay->forceIns();
|
||||||
|
ay->flushWrites();
|
||||||
|
for (DivRegWrite& i: ay->getRegisterWrites()) {
|
||||||
|
immWrite(i.addr&15,i.val);
|
||||||
|
}
|
||||||
|
ay->getRegisterWrites().clear();
|
||||||
|
for (int i=0; i<4; i++) {
|
||||||
|
opChan[i].insChanged=true;
|
||||||
|
if (opChan[i].active) {
|
||||||
|
opChan[i].keyOn=true;
|
||||||
|
opChan[i].freqChanged=true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void* DivPlatformYM2610BExt::getChanState(int ch) {
|
||||||
|
if (ch>=6) return &chan[ch-3];
|
||||||
|
if (ch>=2) return &opChan[ch-2];
|
||||||
|
return &chan[ch];
|
||||||
|
}
|
||||||
|
|
||||||
|
DivDispatchOscBuffer* DivPlatformYM2610BExt::getOscBuffer(int ch) {
|
||||||
|
if (ch>=6) return oscBuf[ch-3];
|
||||||
|
if (ch<3) return oscBuf[ch];
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
void DivPlatformYM2610BExt::reset() {
|
||||||
|
DivPlatformYM2610B::reset();
|
||||||
|
|
||||||
|
for (int i=0; i<4; i++) {
|
||||||
|
opChan[i]=DivPlatformYM2610BExt::OpChannel();
|
||||||
|
opChan[i].vol=127;
|
||||||
|
}
|
||||||
|
|
||||||
|
// channel 2 mode
|
||||||
|
immWrite(0x27,0x40);
|
||||||
|
extMode=true;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool DivPlatformYM2610BExt::keyOffAffectsArp(int ch) {
|
||||||
|
return (ch>8);
|
||||||
|
}
|
||||||
|
|
||||||
|
void DivPlatformYM2610BExt::notifyInsChange(int ins) {
|
||||||
|
DivPlatformYM2610B::notifyInsChange(ins);
|
||||||
|
for (int i=0; i<4; i++) {
|
||||||
|
if (opChan[i].ins==ins) {
|
||||||
|
opChan[i].insChanged=true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
int DivPlatformYM2610BExt::init(DivEngine* parent, int channels, int sugRate, unsigned int flags) {
|
||||||
|
DivPlatformYM2610B::init(parent,channels,sugRate,flags);
|
||||||
|
for (int i=0; i<4; i++) {
|
||||||
|
isOpMuted[i]=false;
|
||||||
|
}
|
||||||
|
|
||||||
|
reset();
|
||||||
|
return 19;
|
||||||
|
}
|
||||||
|
|
||||||
|
void DivPlatformYM2610BExt::quit() {
|
||||||
|
DivPlatformYM2610B::quit();
|
||||||
|
}
|
||||||
|
|
||||||
|
DivPlatformYM2610BExt::~DivPlatformYM2610BExt() {
|
||||||
|
}
|
||||||
51
src/engine/platform/ym2203ext.h
Normal file
51
src/engine/platform/ym2203ext.h
Normal file
|
|
@ -0,0 +1,51 @@
|
||||||
|
/**
|
||||||
|
* Furnace Tracker - multi-system chiptune tracker
|
||||||
|
* Copyright (C) 2021-2022 tildearrow and contributors
|
||||||
|
*
|
||||||
|
* This program is free software; you can redistribute it and/or modify
|
||||||
|
* it under the terms of the GNU General Public License as published by
|
||||||
|
* the Free Software Foundation; either version 2 of the License, or
|
||||||
|
* (at your option) any later version.
|
||||||
|
*
|
||||||
|
* This program is distributed in the hope that it will be useful,
|
||||||
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
|
* GNU General Public License for more details.
|
||||||
|
*
|
||||||
|
* You should have received a copy of the GNU General Public License along
|
||||||
|
* with this program; if not, write to the Free Software Foundation, Inc.,
|
||||||
|
* 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include "../dispatch.h"
|
||||||
|
|
||||||
|
#include "ym2610b.h"
|
||||||
|
|
||||||
|
class DivPlatformYM2610BExt: public DivPlatformYM2610B {
|
||||||
|
struct OpChannel {
|
||||||
|
DivMacroInt std;
|
||||||
|
unsigned char freqH, freqL;
|
||||||
|
int freq, baseFreq, pitch, pitch2, portaPauseFreq, ins;
|
||||||
|
signed char konCycles;
|
||||||
|
bool active, insChanged, freqChanged, keyOn, keyOff, portaPause;
|
||||||
|
int vol;
|
||||||
|
unsigned char pan;
|
||||||
|
OpChannel(): freqH(0), freqL(0), freq(0), baseFreq(0), pitch(0), pitch2(0), portaPauseFreq(0), ins(-1), active(false), insChanged(true), freqChanged(false), keyOn(false), keyOff(false), portaPause(false), vol(0), pan(3) {}
|
||||||
|
};
|
||||||
|
OpChannel opChan[4];
|
||||||
|
bool isOpMuted[4];
|
||||||
|
friend void putDispatchChan(void*,int,int);
|
||||||
|
public:
|
||||||
|
int dispatch(DivCommand c);
|
||||||
|
void* getChanState(int chan);
|
||||||
|
DivDispatchOscBuffer* getOscBuffer(int chan);
|
||||||
|
void reset();
|
||||||
|
void forceIns();
|
||||||
|
void tick(bool sysTick=true);
|
||||||
|
void muteChannel(int ch, bool mute);
|
||||||
|
bool keyOffAffectsArp(int ch);
|
||||||
|
void notifyInsChange(int ins);
|
||||||
|
int init(DivEngine* parent, int channels, int sugRate, unsigned int flags);
|
||||||
|
void quit();
|
||||||
|
~DivPlatformYM2610BExt();
|
||||||
|
};
|
||||||
|
|
@ -20,9 +20,11 @@
|
||||||
#include "ym2608.h"
|
#include "ym2608.h"
|
||||||
#include "sound/ymfm/ymfm.h"
|
#include "sound/ymfm/ymfm.h"
|
||||||
#include "../engine.h"
|
#include "../engine.h"
|
||||||
|
#include "../../ta-log.h"
|
||||||
#include <string.h>
|
#include <string.h>
|
||||||
#include <math.h>
|
#include <math.h>
|
||||||
|
|
||||||
|
#include "sound/ymfm/ymfm_opn.h"
|
||||||
#include "ym2610shared.h"
|
#include "ym2610shared.h"
|
||||||
|
|
||||||
#include "fmshared_OPN.h"
|
#include "fmshared_OPN.h"
|
||||||
|
|
@ -33,7 +35,7 @@ static unsigned char konOffs[6]={
|
||||||
|
|
||||||
#define CHIP_DIVIDER 32
|
#define CHIP_DIVIDER 32
|
||||||
|
|
||||||
const char* regCheatSheetYM2610B[]={
|
const char* regCheatSheetYM2608[]={
|
||||||
// SSG
|
// SSG
|
||||||
"SSG_FreqL_A", "000",
|
"SSG_FreqL_A", "000",
|
||||||
"SSG_FreqH_A", "001",
|
"SSG_FreqH_A", "001",
|
||||||
|
|
@ -181,30 +183,6 @@ const char* regCheatSheetYM2610B[]={
|
||||||
"ADPCMA_Ch4_Vol", "10B",
|
"ADPCMA_Ch4_Vol", "10B",
|
||||||
"ADPCMA_Ch5_Vol", "10C",
|
"ADPCMA_Ch5_Vol", "10C",
|
||||||
"ADPCMA_Ch6_Vol", "10D",
|
"ADPCMA_Ch6_Vol", "10D",
|
||||||
"ADPCMA_Ch1_StL", "110",
|
|
||||||
"ADPCMA_Ch2_StL", "111",
|
|
||||||
"ADPCMA_Ch3_StL", "112",
|
|
||||||
"ADPCMA_Ch4_StL", "113",
|
|
||||||
"ADPCMA_Ch5_StL", "114",
|
|
||||||
"ADPCMA_Ch6_StL", "115",
|
|
||||||
"ADPCMA_Ch1_StH", "118",
|
|
||||||
"ADPCMA_Ch2_StH", "119",
|
|
||||||
"ADPCMA_Ch3_StH", "11A",
|
|
||||||
"ADPCMA_Ch4_StH", "11B",
|
|
||||||
"ADPCMA_Ch5_StH", "11C",
|
|
||||||
"ADPCMA_Ch6_StH", "11D",
|
|
||||||
"ADPCMA_Ch1_EdL", "120",
|
|
||||||
"ADPCMA_Ch2_EdL", "121",
|
|
||||||
"ADPCMA_Ch3_EdL", "122",
|
|
||||||
"ADPCMA_Ch4_EdL", "123",
|
|
||||||
"ADPCMA_Ch5_EdL", "124",
|
|
||||||
"ADPCMA_Ch6_EdL", "125",
|
|
||||||
"ADPCMA_Ch1_EdH", "128",
|
|
||||||
"ADPCMA_Ch2_EdH", "129",
|
|
||||||
"ADPCMA_Ch3_EdH", "12A",
|
|
||||||
"ADPCMA_Ch4_EdH", "12B",
|
|
||||||
"ADPCMA_Ch5_EdH", "12C",
|
|
||||||
"ADPCMA_Ch6_EdH", "12D",
|
|
||||||
// FM (Channel 4-6)
|
// FM (Channel 4-6)
|
||||||
"FM4_Op1_DT_MULT", "130",
|
"FM4_Op1_DT_MULT", "130",
|
||||||
"FM5_Op1_DT_MULT", "131",
|
"FM5_Op1_DT_MULT", "131",
|
||||||
|
|
@ -305,11 +283,11 @@ const char* regCheatSheetYM2610B[]={
|
||||||
NULL
|
NULL
|
||||||
};
|
};
|
||||||
|
|
||||||
const char** DivPlatformYM2610B::getRegisterSheet() {
|
const char** DivPlatformYM2608::getRegisterSheet() {
|
||||||
return regCheatSheetYM2610B;
|
return regCheatSheetYM2608;
|
||||||
}
|
}
|
||||||
|
|
||||||
const char* DivPlatformYM2610B::getEffectName(unsigned char effect) {
|
const char* DivPlatformYM2608::getEffectName(unsigned char effect) {
|
||||||
switch (effect) {
|
switch (effect) {
|
||||||
case 0x10:
|
case 0x10:
|
||||||
return "10xy: Setup LFO (x: enable; y: speed)";
|
return "10xy: Setup LFO (x: enable; y: speed)";
|
||||||
|
|
@ -429,7 +407,7 @@ const char* DivPlatformYM2610B::getEffectName(unsigned char effect) {
|
||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
double DivPlatformYM2610B::NOTE_OPNB(int ch, int note) {
|
double DivPlatformYM2608::NOTE_OPNB(int ch, int note) {
|
||||||
if (ch>8) { // ADPCM-B
|
if (ch>8) { // ADPCM-B
|
||||||
return NOTE_ADPCMB(note);
|
return NOTE_ADPCMB(note);
|
||||||
} else if (ch>5) { // PSG
|
} else if (ch>5) { // PSG
|
||||||
|
|
@ -439,7 +417,7 @@ double DivPlatformYM2610B::NOTE_OPNB(int ch, int note) {
|
||||||
return NOTE_FNUM_BLOCK(note,11);
|
return NOTE_FNUM_BLOCK(note,11);
|
||||||
}
|
}
|
||||||
|
|
||||||
double DivPlatformYM2610B::NOTE_ADPCMB(int note) {
|
double DivPlatformYM2608::NOTE_ADPCMB(int note) {
|
||||||
if (chan[15].sample>=0 && chan[15].sample<parent->song.sampleLen) {
|
if (chan[15].sample>=0 && chan[15].sample<parent->song.sampleLen) {
|
||||||
double off=65535.0*(double)(parent->getSample(chan[15].sample)->centerRate)/8363.0;
|
double off=65535.0*(double)(parent->getSample(chan[15].sample)->centerRate)/8363.0;
|
||||||
return parent->calcBaseFreq((double)chipClock/144,off,note,false);
|
return parent->calcBaseFreq((double)chipClock/144,off,note,false);
|
||||||
|
|
@ -447,10 +425,10 @@ double DivPlatformYM2610B::NOTE_ADPCMB(int note) {
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
void DivPlatformYM2610B::acquire(short* bufL, short* bufR, size_t start, size_t len) {
|
void DivPlatformYM2608::acquire(short* bufL, short* bufR, size_t start, size_t len) {
|
||||||
static int os[2];
|
static int os[2];
|
||||||
|
|
||||||
ymfm::ym2612::fm_engine* fme=fm->debug_fm_engine();
|
ymfm::ym2608::fm_engine* fme=fm->debug_fm_engine();
|
||||||
ymfm::ssg_engine* ssge=fm->debug_ssg_engine();
|
ymfm::ssg_engine* ssge=fm->debug_ssg_engine();
|
||||||
ymfm::adpcm_a_engine* aae=fm->debug_adpcm_a_engine();
|
ymfm::adpcm_a_engine* aae=fm->debug_adpcm_a_engine();
|
||||||
ymfm::adpcm_b_engine* abe=fm->debug_adpcm_b_engine();
|
ymfm::adpcm_b_engine* abe=fm->debug_adpcm_b_engine();
|
||||||
|
|
@ -490,7 +468,6 @@ void DivPlatformYM2610B::acquire(short* bufL, short* bufR, size_t start, size_t
|
||||||
bufL[h]=os[0];
|
bufL[h]=os[0];
|
||||||
bufR[h]=os[1];
|
bufR[h]=os[1];
|
||||||
|
|
||||||
|
|
||||||
for (int i=0; i<6; i++) {
|
for (int i=0; i<6; i++) {
|
||||||
oscBuf[i]->data[oscBuf[i]->needle++]=(fmChan[i]->debug_output(0)+fmChan[i]->debug_output(1));
|
oscBuf[i]->data[oscBuf[i]->needle++]=(fmChan[i]->debug_output(0)+fmChan[i]->debug_output(1));
|
||||||
}
|
}
|
||||||
|
|
@ -508,7 +485,7 @@ void DivPlatformYM2610B::acquire(short* bufL, short* bufR, size_t start, size_t
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void DivPlatformYM2610B::tick(bool sysTick) {
|
void DivPlatformYM2608::tick(bool sysTick) {
|
||||||
// PSG
|
// PSG
|
||||||
ay->tick(sysTick);
|
ay->tick(sysTick);
|
||||||
ay->flushWrites();
|
ay->flushWrites();
|
||||||
|
|
@ -684,7 +661,7 @@ void DivPlatformYM2610B::tick(bool sysTick) {
|
||||||
|
|
||||||
if (chan[15].std.vol.had) {
|
if (chan[15].std.vol.had) {
|
||||||
chan[15].outVol=(chan[15].vol*MIN(64,chan[15].std.vol.val))/64;
|
chan[15].outVol=(chan[15].vol*MIN(64,chan[15].std.vol.val))/64;
|
||||||
immWrite(0x1b,chan[15].outVol);
|
immWrite(0x10b,chan[15].outVol);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (chan[15].std.arp.had) {
|
if (chan[15].std.arp.had) {
|
||||||
|
|
@ -710,11 +687,16 @@ void DivPlatformYM2610B::tick(bool sysTick) {
|
||||||
} else {
|
} else {
|
||||||
chan[15].freq=0;
|
chan[15].freq=0;
|
||||||
}
|
}
|
||||||
immWrite(0x19,chan[15].freq&0xff);
|
immWrite(0x109,chan[15].freq&0xff);
|
||||||
immWrite(0x1a,(chan[15].freq>>8)&0xff);
|
immWrite(0x10a,(chan[15].freq>>8)&0xff);
|
||||||
chan[15].freqChanged=false;
|
chan[15].freqChanged=false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (writeRSSOff) {
|
||||||
|
immWrite(0x10,0x80|writeRSSOff);
|
||||||
|
writeRSSOff=0;
|
||||||
|
}
|
||||||
|
|
||||||
for (int i=16; i<512; i++) {
|
for (int i=16; i<512; i++) {
|
||||||
if (pendingWrites[i]!=oldWrites[i]) {
|
if (pendingWrites[i]!=oldWrites[i]) {
|
||||||
immWrite(i,pendingWrites[i]&0xff);
|
immWrite(i,pendingWrites[i]&0xff);
|
||||||
|
|
@ -750,9 +732,14 @@ void DivPlatformYM2610B::tick(bool sysTick) {
|
||||||
chan[i].keyOn=false;
|
chan[i].keyOn=false;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (writeRSSOn) {
|
||||||
|
immWrite(0x10,writeRSSOn);
|
||||||
|
writeRSSOn=0;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
int DivPlatformYM2610B::dispatch(DivCommand c) {
|
int DivPlatformYM2608::dispatch(DivCommand c) {
|
||||||
if (c.chan>5 && c.chan<9) {
|
if (c.chan>5 && c.chan<9) {
|
||||||
c.chan-=6;
|
c.chan-=6;
|
||||||
return ay->dispatch(c);
|
return ay->dispatch(c);
|
||||||
|
|
@ -771,18 +758,18 @@ int DivPlatformYM2610B::dispatch(DivCommand c) {
|
||||||
chan[c.chan].macroInit(ins);
|
chan[c.chan].macroInit(ins);
|
||||||
if (!chan[c.chan].std.vol.will) {
|
if (!chan[c.chan].std.vol.will) {
|
||||||
chan[c.chan].outVol=chan[c.chan].vol;
|
chan[c.chan].outVol=chan[c.chan].vol;
|
||||||
immWrite(0x1b,chan[c.chan].outVol);
|
immWrite(0x10b,chan[c.chan].outVol);
|
||||||
}
|
}
|
||||||
chan[c.chan].sample=ins->amiga.initSample;
|
chan[c.chan].sample=ins->amiga.getSample(c.value);
|
||||||
if (chan[c.chan].sample>=0 && chan[c.chan].sample<parent->song.sampleLen) {
|
if (chan[c.chan].sample>=0 && chan[c.chan].sample<parent->song.sampleLen) {
|
||||||
DivSample* s=parent->getSample(chan[c.chan].sample);
|
DivSample* s=parent->getSample(chan[c.chan].sample);
|
||||||
immWrite(0x12,(s->offB>>8)&0xff);
|
immWrite(0x102,(s->offB>>5)&0xff);
|
||||||
immWrite(0x13,s->offB>>16);
|
immWrite(0x103,(s->offB>>13)&0xff);
|
||||||
int end=s->offB+s->lengthB-1;
|
int end=s->offB+s->lengthB-1;
|
||||||
immWrite(0x14,(end>>8)&0xff);
|
immWrite(0x104,(end>>5)&0xff);
|
||||||
immWrite(0x15,end>>16);
|
immWrite(0x105,(end>>13)&0xff);
|
||||||
immWrite(0x11,isMuted[c.chan]?0:(chan[c.chan].pan<<6));
|
immWrite(0x101,(isMuted[c.chan]?0:(chan[c.chan].pan<<6))|2);
|
||||||
immWrite(0x10,(s->loopStart>=0)?0x90:0x80); // start/repeat
|
immWrite(0x100,(s->loopStart>=0)?0xb0:0xa0); // start/repeat
|
||||||
if (c.value!=DIV_NOTE_NULL) {
|
if (c.value!=DIV_NOTE_NULL) {
|
||||||
chan[c.chan].note=c.value;
|
chan[c.chan].note=c.value;
|
||||||
chan[c.chan].baseFreq=NOTE_ADPCMB(chan[c.chan].note);
|
chan[c.chan].baseFreq=NOTE_ADPCMB(chan[c.chan].note);
|
||||||
|
|
@ -791,11 +778,11 @@ int DivPlatformYM2610B::dispatch(DivCommand c) {
|
||||||
chan[c.chan].active=true;
|
chan[c.chan].active=true;
|
||||||
chan[c.chan].keyOn=true;
|
chan[c.chan].keyOn=true;
|
||||||
} else {
|
} else {
|
||||||
immWrite(0x10,0x01); // reset
|
immWrite(0x100,0x01); // reset
|
||||||
immWrite(0x12,0);
|
immWrite(0x102,0);
|
||||||
immWrite(0x13,0);
|
immWrite(0x103,0);
|
||||||
immWrite(0x14,0);
|
immWrite(0x104,0);
|
||||||
immWrite(0x15,0);
|
immWrite(0x105,0);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
|
|
@ -803,44 +790,33 @@ int DivPlatformYM2610B::dispatch(DivCommand c) {
|
||||||
chan[c.chan].macroInit(NULL);
|
chan[c.chan].macroInit(NULL);
|
||||||
chan[c.chan].outVol=chan[c.chan].vol;
|
chan[c.chan].outVol=chan[c.chan].vol;
|
||||||
if ((12*sampleBank+c.value%12)>=parent->song.sampleLen) {
|
if ((12*sampleBank+c.value%12)>=parent->song.sampleLen) {
|
||||||
immWrite(0x10,0x01); // reset
|
immWrite(0x100,0x01); // reset
|
||||||
immWrite(0x12,0);
|
immWrite(0x102,0);
|
||||||
immWrite(0x13,0);
|
immWrite(0x103,0);
|
||||||
immWrite(0x14,0);
|
immWrite(0x104,0);
|
||||||
immWrite(0x15,0);
|
immWrite(0x105,0);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
DivSample* s=parent->getSample(12*sampleBank+c.value%12);
|
DivSample* s=parent->getSample(12*sampleBank+c.value%12);
|
||||||
immWrite(0x12,(s->offB>>8)&0xff);
|
immWrite(0x102,(s->offB>>5)&0xff);
|
||||||
immWrite(0x13,s->offB>>16);
|
immWrite(0x103,(s->offB>>13)&0xff);
|
||||||
int end=s->offB+s->lengthB-1;
|
int end=s->offB+s->lengthB-1;
|
||||||
immWrite(0x14,(end>>8)&0xff);
|
immWrite(0x104,(end>>5)&0xff);
|
||||||
immWrite(0x15,end>>16);
|
immWrite(0x105,(end>>13)&0xff);
|
||||||
immWrite(0x11,isMuted[c.chan]?0:(chan[c.chan].pan<<6));
|
immWrite(0x101,(isMuted[c.chan]?0:(chan[c.chan].pan<<6))|2);
|
||||||
immWrite(0x10,(s->loopStart>=0)?0x90:0x80); // start/repeat
|
immWrite(0x100,(s->loopStart>=0)?0xb0:0xa0); // start/repeat
|
||||||
chan[c.chan].baseFreq=(((unsigned int)s->rate)<<16)/(chipClock/144);
|
int freq=(65536.0*(double)s->rate)/((double)chipClock/144.0);
|
||||||
chan[c.chan].freqChanged=true;
|
immWrite(0x109,freq&0xff);
|
||||||
|
immWrite(0x10a,(freq>>8)&0xff);
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
if (c.chan>8) { // ADPCM-A
|
if (c.chan>8) { // RSS
|
||||||
if (skipRegisterWrites) break;
|
if (skipRegisterWrites) break;
|
||||||
if ((12*sampleBank+c.value%12)>=parent->song.sampleLen) {
|
if (!isMuted[c.chan]) {
|
||||||
immWrite(0x100,0x80|(1<<(c.chan-9)));
|
writeRSSOn|=(1<<(c.chan-9));
|
||||||
immWrite(0x110+c.chan-9,0);
|
|
||||||
immWrite(0x118+c.chan-9,0);
|
|
||||||
immWrite(0x120+c.chan-9,0);
|
|
||||||
immWrite(0x128+c.chan-9,0);
|
|
||||||
break;
|
|
||||||
}
|
}
|
||||||
DivSample* s=parent->getSample(12*sampleBank+c.value%12);
|
immWrite(0x18+(c.chan-9),isMuted[c.chan]?0:((chan[c.chan].pan<<6)|chan[c.chan].vol));
|
||||||
immWrite(0x110+c.chan-9,(s->offA>>8)&0xff);
|
|
||||||
immWrite(0x118+c.chan-9,s->offA>>16);
|
|
||||||
int end=s->offA+s->lengthA-1;
|
|
||||||
immWrite(0x120+c.chan-9,(end>>8)&0xff);
|
|
||||||
immWrite(0x128+c.chan-9,end>>16);
|
|
||||||
immWrite(0x108+(c.chan-9),isMuted[c.chan]?0:((chan[c.chan].pan<<6)|chan[c.chan].vol));
|
|
||||||
immWrite(0x100,0x00|(1<<(c.chan-9)));
|
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
DivInstrument* ins=parent->getIns(chan[c.chan].ins,DIV_INS_FM);
|
DivInstrument* ins=parent->getIns(chan[c.chan].ins,DIV_INS_FM);
|
||||||
|
|
@ -894,11 +870,11 @@ int DivPlatformYM2610B::dispatch(DivCommand c) {
|
||||||
}
|
}
|
||||||
case DIV_CMD_NOTE_OFF:
|
case DIV_CMD_NOTE_OFF:
|
||||||
if (c.chan>14) {
|
if (c.chan>14) {
|
||||||
immWrite(0x10,0x01); // reset
|
immWrite(0x100,0x01); // reset
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
if (c.chan>8) {
|
if (c.chan>8) {
|
||||||
immWrite(0x100,0x80|(1<<(c.chan-9)));
|
writeRSSOff|=1<<(c.chan-9);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
chan[c.chan].keyOff=true;
|
chan[c.chan].keyOff=true;
|
||||||
|
|
@ -908,11 +884,11 @@ int DivPlatformYM2610B::dispatch(DivCommand c) {
|
||||||
break;
|
break;
|
||||||
case DIV_CMD_NOTE_OFF_ENV:
|
case DIV_CMD_NOTE_OFF_ENV:
|
||||||
if (c.chan>14) {
|
if (c.chan>14) {
|
||||||
immWrite(0x10,0x01); // reset
|
immWrite(0x100,0x01); // reset
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
if (c.chan>8) {
|
if (c.chan>8) {
|
||||||
immWrite(0x100,0x80|(1<<(c.chan-9)));
|
writeRSSOff|=1<<(c.chan-9);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
chan[c.chan].keyOff=true;
|
chan[c.chan].keyOff=true;
|
||||||
|
|
@ -929,11 +905,11 @@ int DivPlatformYM2610B::dispatch(DivCommand c) {
|
||||||
chan[c.chan].outVol=c.value;
|
chan[c.chan].outVol=c.value;
|
||||||
}
|
}
|
||||||
if (c.chan>14) { // ADPCM-B
|
if (c.chan>14) { // ADPCM-B
|
||||||
immWrite(0x1b,chan[c.chan].outVol);
|
immWrite(0x10b,chan[c.chan].outVol);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
if (c.chan>8) { // ADPCM-A
|
if (c.chan>8) { // ADPCM-A
|
||||||
immWrite(0x108+(c.chan-9),isMuted[c.chan]?0:((chan[c.chan].pan<<6)|chan[c.chan].vol));
|
immWrite(0x18+(c.chan-9),isMuted[c.chan]?0:((chan[c.chan].pan<<6)|chan[c.chan].vol));
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
for (int i=0; i<4; i++) {
|
for (int i=0; i<4; i++) {
|
||||||
|
|
@ -964,17 +940,18 @@ int DivPlatformYM2610B::dispatch(DivCommand c) {
|
||||||
chan[c.chan].pan=(c.value2>0)|((c.value>0)<<1);
|
chan[c.chan].pan=(c.value2>0)|((c.value>0)<<1);
|
||||||
}
|
}
|
||||||
if (c.chan>14) {
|
if (c.chan>14) {
|
||||||
immWrite(0x11,isMuted[c.chan]?0:(chan[c.chan].pan<<6));
|
immWrite(0x101,(isMuted[c.chan]?0:(chan[c.chan].pan<<6))|2);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
if (c.chan>8) {
|
if (c.chan>8) {
|
||||||
immWrite(0x108+(c.chan-9),isMuted[c.chan]?0:((chan[c.chan].pan<<6)|chan[c.chan].vol));
|
immWrite(0x18+(c.chan-9),isMuted[c.chan]?0:((chan[c.chan].pan<<6)|chan[c.chan].vol));
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
rWrite(chanOffs[c.chan]+ADDR_LRAF,(isMuted[c.chan]?0:(chan[c.chan].pan<<6))|(chan[c.chan].state.fms&7)|((chan[c.chan].state.ams&3)<<4));
|
rWrite(chanOffs[c.chan]+ADDR_LRAF,(isMuted[c.chan]?0:(chan[c.chan].pan<<6))|(chan[c.chan].state.fms&7)|((chan[c.chan].state.ams&3)<<4));
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
case DIV_CMD_PITCH: {
|
case DIV_CMD_PITCH: {
|
||||||
|
if (c.chan==15 && !chan[c.chan].furnacePCM) break;
|
||||||
chan[c.chan].pitch=c.value;
|
chan[c.chan].pitch=c.value;
|
||||||
chan[c.chan].freqChanged=true;
|
chan[c.chan].freqChanged=true;
|
||||||
break;
|
break;
|
||||||
|
|
@ -1055,6 +1032,7 @@ int DivPlatformYM2610B::dispatch(DivCommand c) {
|
||||||
iface.sampleBank=sampleBank;
|
iface.sampleBank=sampleBank;
|
||||||
break;
|
break;
|
||||||
case DIV_CMD_LEGATO: {
|
case DIV_CMD_LEGATO: {
|
||||||
|
if (c.chan==15 && !chan[c.chan].furnacePCM) break;
|
||||||
chan[c.chan].baseFreq=NOTE_OPNB(c.chan,c.value);
|
chan[c.chan].baseFreq=NOTE_OPNB(c.chan,c.value);
|
||||||
chan[c.chan].freqChanged=true;
|
chan[c.chan].freqChanged=true;
|
||||||
break;
|
break;
|
||||||
|
|
@ -1263,13 +1241,13 @@ int DivPlatformYM2610B::dispatch(DivCommand c) {
|
||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
void DivPlatformYM2610B::muteChannel(int ch, bool mute) {
|
void DivPlatformYM2608::muteChannel(int ch, bool mute) {
|
||||||
isMuted[ch]=mute;
|
isMuted[ch]=mute;
|
||||||
if (ch>14) { // ADPCM-B
|
if (ch>14) { // ADPCM-B
|
||||||
immWrite(0x11,isMuted[ch]?0:(chan[ch].pan<<6));
|
immWrite(0x101,(isMuted[ch]?0:(chan[ch].pan<<6))|2);
|
||||||
}
|
}
|
||||||
if (ch>8) { // ADPCM-A
|
if (ch>8) { // ADPCM-A
|
||||||
immWrite(0x108+(ch-9),isMuted[ch]?0:((chan[ch].pan<<6)|chan[ch].vol));
|
immWrite(0x18+(ch-9),isMuted[ch]?0:((chan[ch].pan<<6)|chan[ch].vol));
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
if (ch>5) { // PSG
|
if (ch>5) { // PSG
|
||||||
|
|
@ -1280,7 +1258,7 @@ void DivPlatformYM2610B::muteChannel(int ch, bool mute) {
|
||||||
rWrite(chanOffs[ch]+ADDR_LRAF,(isMuted[ch]?0:(chan[ch].pan<<6))|(chan[ch].state.fms&7)|((chan[ch].state.ams&3)<<4));
|
rWrite(chanOffs[ch]+ADDR_LRAF,(isMuted[ch]?0:(chan[ch].pan<<6))|(chan[ch].state.fms&7)|((chan[ch].state.ams&3)<<4));
|
||||||
}
|
}
|
||||||
|
|
||||||
void DivPlatformYM2610B::forceIns() {
|
void DivPlatformYM2608::forceIns() {
|
||||||
for (int i=0; i<6; i++) {
|
for (int i=0; i<6; i++) {
|
||||||
for (int j=0; j<4; j++) {
|
for (int j=0; j<4; j++) {
|
||||||
unsigned short baseAddr=chanOffs[i]|opOffs[j];
|
unsigned short baseAddr=chanOffs[i]|opOffs[j];
|
||||||
|
|
@ -1316,31 +1294,31 @@ void DivPlatformYM2610B::forceIns() {
|
||||||
ay->getRegisterWrites().clear();
|
ay->getRegisterWrites().clear();
|
||||||
}
|
}
|
||||||
|
|
||||||
void* DivPlatformYM2610B::getChanState(int ch) {
|
void* DivPlatformYM2608::getChanState(int ch) {
|
||||||
return &chan[ch];
|
return &chan[ch];
|
||||||
}
|
}
|
||||||
|
|
||||||
DivDispatchOscBuffer* DivPlatformYM2610B::getOscBuffer(int ch) {
|
DivDispatchOscBuffer* DivPlatformYM2608::getOscBuffer(int ch) {
|
||||||
return oscBuf[ch];
|
return oscBuf[ch];
|
||||||
}
|
}
|
||||||
|
|
||||||
unsigned char* DivPlatformYM2610B::getRegisterPool() {
|
unsigned char* DivPlatformYM2608::getRegisterPool() {
|
||||||
return regPool;
|
return regPool;
|
||||||
}
|
}
|
||||||
|
|
||||||
int DivPlatformYM2610B::getRegisterPoolSize() {
|
int DivPlatformYM2608::getRegisterPoolSize() {
|
||||||
return 512;
|
return 512;
|
||||||
}
|
}
|
||||||
|
|
||||||
void DivPlatformYM2610B::poke(unsigned int addr, unsigned short val) {
|
void DivPlatformYM2608::poke(unsigned int addr, unsigned short val) {
|
||||||
immWrite(addr,val);
|
immWrite(addr,val);
|
||||||
}
|
}
|
||||||
|
|
||||||
void DivPlatformYM2610B::poke(std::vector<DivRegWrite>& wlist) {
|
void DivPlatformYM2608::poke(std::vector<DivRegWrite>& wlist) {
|
||||||
for (DivRegWrite& i: wlist) immWrite(i.addr,i.val);
|
for (DivRegWrite& i: wlist) immWrite(i.addr,i.val);
|
||||||
}
|
}
|
||||||
|
|
||||||
void DivPlatformYM2610B::reset() {
|
void DivPlatformYM2608::reset() {
|
||||||
while (!writes.empty()) writes.pop();
|
while (!writes.empty()) writes.pop();
|
||||||
memset(regPool,0,512);
|
memset(regPool,0,512);
|
||||||
if (dumpWrites) {
|
if (dumpWrites) {
|
||||||
|
|
@ -1348,7 +1326,7 @@ void DivPlatformYM2610B::reset() {
|
||||||
}
|
}
|
||||||
fm->reset();
|
fm->reset();
|
||||||
for (int i=0; i<16; i++) {
|
for (int i=0; i<16; i++) {
|
||||||
chan[i]=DivPlatformYM2610B::Channel();
|
chan[i]=DivPlatformYM2608::Channel();
|
||||||
chan[i].std.setEngine(parent);
|
chan[i].std.setEngine(parent);
|
||||||
}
|
}
|
||||||
for (int i=0; i<6; i++) {
|
for (int i=0; i<6; i++) {
|
||||||
|
|
@ -1370,6 +1348,8 @@ void DivPlatformYM2610B::reset() {
|
||||||
|
|
||||||
lastBusy=60;
|
lastBusy=60;
|
||||||
sampleBank=0;
|
sampleBank=0;
|
||||||
|
writeRSSOff=0;
|
||||||
|
writeRSSOn=0;
|
||||||
|
|
||||||
delay=0;
|
delay=0;
|
||||||
|
|
||||||
|
|
@ -1379,23 +1359,30 @@ void DivPlatformYM2610B::reset() {
|
||||||
immWrite(0x22,0x08);
|
immWrite(0x22,0x08);
|
||||||
|
|
||||||
// PCM volume
|
// PCM volume
|
||||||
immWrite(0x101,0x3f); // A
|
immWrite(0x11,0x3f); // A
|
||||||
immWrite(0x1b,0xff); // B
|
immWrite(0x10b,0xff); // B
|
||||||
|
|
||||||
|
// ADPCM limit
|
||||||
|
immWrite(0x10d,0xff);
|
||||||
|
immWrite(0x10c,0xff);
|
||||||
|
|
||||||
|
// enable 6 channel mode
|
||||||
|
immWrite(0x29,0x80);
|
||||||
|
|
||||||
ay->reset();
|
ay->reset();
|
||||||
ay->getRegisterWrites().clear();
|
ay->getRegisterWrites().clear();
|
||||||
ay->flushWrites();
|
ay->flushWrites();
|
||||||
}
|
}
|
||||||
|
|
||||||
bool DivPlatformYM2610B::isStereo() {
|
bool DivPlatformYM2608::isStereo() {
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool DivPlatformYM2610B::keyOffAffectsArp(int ch) {
|
bool DivPlatformYM2608::keyOffAffectsArp(int ch) {
|
||||||
return (ch>5);
|
return (ch>5);
|
||||||
}
|
}
|
||||||
|
|
||||||
void DivPlatformYM2610B::notifyInsChange(int ins) {
|
void DivPlatformYM2608::notifyInsChange(int ins) {
|
||||||
for (int i=0; i<16; i++) {
|
for (int i=0; i<16; i++) {
|
||||||
if (chan[i].ins==ins) {
|
if (chan[i].ins==ins) {
|
||||||
chan[i].insChanged=true;
|
chan[i].insChanged=true;
|
||||||
|
|
@ -1404,17 +1391,59 @@ void DivPlatformYM2610B::notifyInsChange(int ins) {
|
||||||
ay->notifyInsChange(ins);
|
ay->notifyInsChange(ins);
|
||||||
}
|
}
|
||||||
|
|
||||||
void DivPlatformYM2610B::notifyInsDeletion(void* ins) {
|
void DivPlatformYM2608::notifyInsDeletion(void* ins) {
|
||||||
ay->notifyInsDeletion(ins);
|
ay->notifyInsDeletion(ins);
|
||||||
}
|
}
|
||||||
|
|
||||||
void DivPlatformYM2610B::setSkipRegisterWrites(bool value) {
|
void DivPlatformYM2608::setSkipRegisterWrites(bool value) {
|
||||||
DivDispatch::setSkipRegisterWrites(value);
|
DivDispatch::setSkipRegisterWrites(value);
|
||||||
ay->setSkipRegisterWrites(value);
|
ay->setSkipRegisterWrites(value);
|
||||||
}
|
}
|
||||||
|
|
||||||
int DivPlatformYM2610B::init(DivEngine* p, int channels, int sugRate, unsigned int flags) {
|
const void* DivPlatformYM2608::getSampleMem(int index) {
|
||||||
DivPlatformYM2610Base::init(p, channels, sugRate, flags);
|
return index == 0 ? adpcmBMem : NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
size_t DivPlatformYM2608::getSampleMemCapacity(int index) {
|
||||||
|
return index == 0 ? 2097152 : 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
size_t DivPlatformYM2608::getSampleMemUsage(int index) {
|
||||||
|
return index == 0 ? adpcmBMemLen : 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
void DivPlatformYM2608::renderSamples() {
|
||||||
|
memset(adpcmBMem,0,getSampleMemCapacity(0));
|
||||||
|
|
||||||
|
size_t memPos=0;
|
||||||
|
for (int i=0; i<parent->song.sampleLen; i++) {
|
||||||
|
DivSample* s=parent->song.sample[i];
|
||||||
|
int paddedLen=(s->lengthB+255)&(~0xff);
|
||||||
|
if ((memPos&0xf00000)!=((memPos+paddedLen)&0xf00000)) {
|
||||||
|
memPos=(memPos+0xfffff)&0xf00000;
|
||||||
|
}
|
||||||
|
if (memPos>=getSampleMemCapacity(0)) {
|
||||||
|
logW("out of ADPCM memory for sample %d!",i);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
if (memPos+paddedLen>=getSampleMemCapacity(0)) {
|
||||||
|
memcpy(adpcmBMem+memPos,s->dataB,getSampleMemCapacity(0)-memPos);
|
||||||
|
logW("out of ADPCM memory for sample %d!",i);
|
||||||
|
} else {
|
||||||
|
memcpy(adpcmBMem+memPos,s->dataB,paddedLen);
|
||||||
|
}
|
||||||
|
s->offB=memPos;
|
||||||
|
memPos+=paddedLen;
|
||||||
|
}
|
||||||
|
adpcmBMemLen=memPos+256;
|
||||||
|
}
|
||||||
|
|
||||||
|
int DivPlatformYM2608::init(DivEngine* p, int channels, int sugRate, unsigned int flags) {
|
||||||
|
parent=p;
|
||||||
|
adpcmBMem=new unsigned char[getSampleMemCapacity(0)];
|
||||||
|
adpcmBMemLen=0;
|
||||||
|
iface.adpcmBMem=adpcmBMem;
|
||||||
|
iface.sampleBank=0;
|
||||||
dumpWrites=false;
|
dumpWrites=false;
|
||||||
skipRegisterWrites=false;
|
skipRegisterWrites=false;
|
||||||
for (int i=0; i<16; i++) {
|
for (int i=0; i<16; i++) {
|
||||||
|
|
@ -1422,11 +1451,12 @@ int DivPlatformYM2610B::init(DivEngine* p, int channels, int sugRate, unsigned i
|
||||||
oscBuf[i]=new DivDispatchOscBuffer;
|
oscBuf[i]=new DivDispatchOscBuffer;
|
||||||
}
|
}
|
||||||
chipClock=8000000;
|
chipClock=8000000;
|
||||||
rate=chipClock/16;
|
fm=new ymfm::ym2608(iface);
|
||||||
|
fm->set_fidelity(ymfm::OPN_FIDELITY_MIN);
|
||||||
|
rate=fm->sample_rate(chipClock);
|
||||||
for (int i=0; i<16; i++) {
|
for (int i=0; i<16; i++) {
|
||||||
oscBuf[i]->rate=rate;
|
oscBuf[i]->rate=rate;
|
||||||
}
|
}
|
||||||
fm=new ymfm::ym2610b(iface);
|
|
||||||
// YM2149, 2MHz
|
// YM2149, 2MHz
|
||||||
ay=new DivPlatformAY8910;
|
ay=new DivPlatformAY8910;
|
||||||
ay->init(p,3,sugRate,35);
|
ay->init(p,3,sugRate,35);
|
||||||
|
|
@ -1435,15 +1465,15 @@ int DivPlatformYM2610B::init(DivEngine* p, int channels, int sugRate, unsigned i
|
||||||
return 16;
|
return 16;
|
||||||
}
|
}
|
||||||
|
|
||||||
void DivPlatformYM2610B::quit() {
|
void DivPlatformYM2608::quit() {
|
||||||
for (int i=0; i<16; i++) {
|
for (int i=0; i<16; i++) {
|
||||||
delete oscBuf[i];
|
delete oscBuf[i];
|
||||||
}
|
}
|
||||||
ay->quit();
|
ay->quit();
|
||||||
delete ay;
|
delete ay;
|
||||||
delete fm;
|
delete fm;
|
||||||
DivPlatformYM2610Base::quit();
|
delete[] adpcmBMem;
|
||||||
}
|
}
|
||||||
|
|
||||||
DivPlatformYM2610B::~DivPlatformYM2610B() {
|
DivPlatformYM2608::~DivPlatformYM2608() {
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -24,9 +24,18 @@
|
||||||
#include <queue>
|
#include <queue>
|
||||||
#include "sound/ymfm/ymfm_opn.h"
|
#include "sound/ymfm/ymfm_opn.h"
|
||||||
|
|
||||||
#include "ym2610.h"
|
#include "ay.h"
|
||||||
|
|
||||||
class DivPlatformYM2608: public DivPlatformYM2610Base {
|
class DivYM2608Interface: public ymfm::ymfm_interface {
|
||||||
|
public:
|
||||||
|
unsigned char* adpcmBMem;
|
||||||
|
int sampleBank;
|
||||||
|
uint8_t ymfm_external_read(ymfm::access_class type, uint32_t address);
|
||||||
|
void ymfm_external_write(ymfm::access_class type, uint32_t address, uint8_t data);
|
||||||
|
DivYM2608Interface(): adpcmBMem(NULL), sampleBank(0) {}
|
||||||
|
};
|
||||||
|
|
||||||
|
class DivPlatformYM2608: public DivDispatch {
|
||||||
protected:
|
protected:
|
||||||
const unsigned short chanOffs[6]={
|
const unsigned short chanOffs[6]={
|
||||||
0x00, 0x01, 0x02, 0x100, 0x101, 0x102
|
0x00, 0x01, 0x02, 0x100, 0x101, 0x102
|
||||||
|
|
@ -88,9 +97,14 @@ class DivPlatformYM2608: public DivPlatformYM2610Base {
|
||||||
ymfm::ym2608::output_data fmout;
|
ymfm::ym2608::output_data fmout;
|
||||||
unsigned char regPool[512];
|
unsigned char regPool[512];
|
||||||
unsigned char lastBusy;
|
unsigned char lastBusy;
|
||||||
|
|
||||||
|
unsigned char* adpcmBMem;
|
||||||
|
size_t adpcmBMemLen;
|
||||||
|
DivYM2608Interface iface;
|
||||||
|
|
||||||
DivPlatformAY8910* ay;
|
DivPlatformAY8910* ay;
|
||||||
unsigned char sampleBank;
|
unsigned char sampleBank;
|
||||||
|
unsigned char writeRSSOff, writeRSSOn;
|
||||||
|
|
||||||
int delay;
|
int delay;
|
||||||
|
|
||||||
|
|
@ -123,6 +137,10 @@ class DivPlatformYM2608: public DivPlatformYM2610Base {
|
||||||
void poke(std::vector<DivRegWrite>& wlist);
|
void poke(std::vector<DivRegWrite>& wlist);
|
||||||
const char** getRegisterSheet();
|
const char** getRegisterSheet();
|
||||||
const char* getEffectName(unsigned char effect);
|
const char* getEffectName(unsigned char effect);
|
||||||
|
const void* getSampleMem(int index);
|
||||||
|
size_t getSampleMemCapacity(int index);
|
||||||
|
size_t getSampleMemUsage(int index);
|
||||||
|
void renderSamples();
|
||||||
int init(DivEngine* parent, int channels, int sugRate, unsigned int flags);
|
int init(DivEngine* parent, int channels, int sugRate, unsigned int flags);
|
||||||
void quit();
|
void quit();
|
||||||
~DivPlatformYM2608();
|
~DivPlatformYM2608();
|
||||||
|
|
|
||||||
42
src/engine/platform/ym2608Interface.cpp
Normal file
42
src/engine/platform/ym2608Interface.cpp
Normal file
|
|
@ -0,0 +1,42 @@
|
||||||
|
/**
|
||||||
|
* Furnace Tracker - multi-system chiptune tracker
|
||||||
|
* Copyright (C) 2021-2022 tildearrow and contributors
|
||||||
|
*
|
||||||
|
* This program is free software; you can redistribute it and/or modify
|
||||||
|
* it under the terms of the GNU General Public License as published by
|
||||||
|
* the Free Software Foundation; either version 2 of the License, or
|
||||||
|
* (at your option) any later version.
|
||||||
|
*
|
||||||
|
* This program is distributed in the hope that it will be useful,
|
||||||
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
|
* GNU General Public License for more details.
|
||||||
|
*
|
||||||
|
* You should have received a copy of the GNU General Public License along
|
||||||
|
* with this program; if not, write to the Free Software Foundation, Inc.,
|
||||||
|
* 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include "sound/ymfm/ymfm.h"
|
||||||
|
#include "ym2608.h"
|
||||||
|
#include "../engine.h"
|
||||||
|
|
||||||
|
#include "sound/rss.h"
|
||||||
|
|
||||||
|
uint8_t DivYM2608Interface::ymfm_external_read(ymfm::access_class type, uint32_t address) {
|
||||||
|
switch (type) {
|
||||||
|
case ymfm::ACCESS_ADPCM_A:
|
||||||
|
return YM2608_ADPCM_ROM[address&0x1fff];
|
||||||
|
case ymfm::ACCESS_ADPCM_B:
|
||||||
|
if (adpcmBMem==NULL) {
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
return adpcmBMem[address&0xffffff];
|
||||||
|
default:
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
void DivYM2608Interface::ymfm_external_write(ymfm::access_class type, uint32_t address, uint8_t data) {
|
||||||
|
}
|
||||||
|
|
@ -470,7 +470,7 @@ double DivPlatformYM2610::NOTE_ADPCMB(int note) {
|
||||||
void DivPlatformYM2610::acquire(short* bufL, short* bufR, size_t start, size_t len) {
|
void DivPlatformYM2610::acquire(short* bufL, short* bufR, size_t start, size_t len) {
|
||||||
static int os[2];
|
static int os[2];
|
||||||
|
|
||||||
ymfm::ym2612::fm_engine* fme=fm->debug_fm_engine();
|
ymfm::ym2610::fm_engine* fme=fm->debug_fm_engine();
|
||||||
ymfm::ssg_engine* ssge=fm->debug_ssg_engine();
|
ymfm::ssg_engine* ssge=fm->debug_ssg_engine();
|
||||||
ymfm::adpcm_a_engine* aae=fm->debug_adpcm_a_engine();
|
ymfm::adpcm_a_engine* aae=fm->debug_adpcm_a_engine();
|
||||||
ymfm::adpcm_b_engine* abe=fm->debug_adpcm_b_engine();
|
ymfm::adpcm_b_engine* abe=fm->debug_adpcm_b_engine();
|
||||||
|
|
@ -795,7 +795,7 @@ int DivPlatformYM2610::dispatch(DivCommand c) {
|
||||||
chan[c.chan].outVol=chan[c.chan].vol;
|
chan[c.chan].outVol=chan[c.chan].vol;
|
||||||
immWrite(0x1b,chan[c.chan].outVol);
|
immWrite(0x1b,chan[c.chan].outVol);
|
||||||
}
|
}
|
||||||
chan[c.chan].sample=ins->amiga.initSample;
|
chan[c.chan].sample=ins->amiga.getSample(c.value);
|
||||||
if (chan[c.chan].sample>=0 && chan[c.chan].sample<parent->song.sampleLen) {
|
if (chan[c.chan].sample>=0 && chan[c.chan].sample<parent->song.sampleLen) {
|
||||||
DivSample* s=parent->getSample(chan[c.chan].sample);
|
DivSample* s=parent->getSample(chan[c.chan].sample);
|
||||||
immWrite(0x12,(s->offB>>8)&0xff);
|
immWrite(0x12,(s->offB>>8)&0xff);
|
||||||
|
|
@ -840,8 +840,9 @@ int DivPlatformYM2610::dispatch(DivCommand c) {
|
||||||
immWrite(0x15,end>>16);
|
immWrite(0x15,end>>16);
|
||||||
immWrite(0x11,isMuted[c.chan]?0:(chan[c.chan].pan<<6));
|
immWrite(0x11,isMuted[c.chan]?0:(chan[c.chan].pan<<6));
|
||||||
immWrite(0x10,(s->loopStart>=0)?0x90:0x80); // start/repeat
|
immWrite(0x10,(s->loopStart>=0)?0x90:0x80); // start/repeat
|
||||||
chan[c.chan].baseFreq=(((unsigned int)s->rate)<<16)/(chipClock/144);
|
int freq=(65536.0*(double)s->rate)/((double)chipClock/144.0);
|
||||||
chan[c.chan].freqChanged=true;
|
immWrite(0x19,freq&0xff);
|
||||||
|
immWrite(0x1a,(freq>>8)&0xff);
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
@ -997,6 +998,7 @@ int DivPlatformYM2610::dispatch(DivCommand c) {
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
case DIV_CMD_PITCH: {
|
case DIV_CMD_PITCH: {
|
||||||
|
if (c.chan==13 && !chan[c.chan].furnacePCM) break;
|
||||||
chan[c.chan].pitch=c.value;
|
chan[c.chan].pitch=c.value;
|
||||||
chan[c.chan].freqChanged=true;
|
chan[c.chan].freqChanged=true;
|
||||||
break;
|
break;
|
||||||
|
|
@ -1077,6 +1079,7 @@ int DivPlatformYM2610::dispatch(DivCommand c) {
|
||||||
iface.sampleBank=sampleBank;
|
iface.sampleBank=sampleBank;
|
||||||
break;
|
break;
|
||||||
case DIV_CMD_LEGATO: {
|
case DIV_CMD_LEGATO: {
|
||||||
|
if (c.chan==13 && !chan[c.chan].furnacePCM) break;
|
||||||
chan[c.chan].baseFreq=NOTE_OPNB(c.chan,c.value);
|
chan[c.chan].baseFreq=NOTE_OPNB(c.chan,c.value);
|
||||||
chan[c.chan].freqChanged=true;
|
chan[c.chan].freqChanged=true;
|
||||||
break;
|
break;
|
||||||
|
|
|
||||||
|
|
@ -450,7 +450,7 @@ double DivPlatformYM2610B::NOTE_ADPCMB(int note) {
|
||||||
void DivPlatformYM2610B::acquire(short* bufL, short* bufR, size_t start, size_t len) {
|
void DivPlatformYM2610B::acquire(short* bufL, short* bufR, size_t start, size_t len) {
|
||||||
static int os[2];
|
static int os[2];
|
||||||
|
|
||||||
ymfm::ym2612::fm_engine* fme=fm->debug_fm_engine();
|
ymfm::ym2610b::fm_engine* fme=fm->debug_fm_engine();
|
||||||
ymfm::ssg_engine* ssge=fm->debug_ssg_engine();
|
ymfm::ssg_engine* ssge=fm->debug_ssg_engine();
|
||||||
ymfm::adpcm_a_engine* aae=fm->debug_adpcm_a_engine();
|
ymfm::adpcm_a_engine* aae=fm->debug_adpcm_a_engine();
|
||||||
ymfm::adpcm_b_engine* abe=fm->debug_adpcm_b_engine();
|
ymfm::adpcm_b_engine* abe=fm->debug_adpcm_b_engine();
|
||||||
|
|
@ -773,7 +773,7 @@ int DivPlatformYM2610B::dispatch(DivCommand c) {
|
||||||
chan[c.chan].outVol=chan[c.chan].vol;
|
chan[c.chan].outVol=chan[c.chan].vol;
|
||||||
immWrite(0x1b,chan[c.chan].outVol);
|
immWrite(0x1b,chan[c.chan].outVol);
|
||||||
}
|
}
|
||||||
chan[c.chan].sample=ins->amiga.initSample;
|
chan[c.chan].sample=ins->amiga.getSample(c.value);
|
||||||
if (chan[c.chan].sample>=0 && chan[c.chan].sample<parent->song.sampleLen) {
|
if (chan[c.chan].sample>=0 && chan[c.chan].sample<parent->song.sampleLen) {
|
||||||
DivSample* s=parent->getSample(chan[c.chan].sample);
|
DivSample* s=parent->getSample(chan[c.chan].sample);
|
||||||
immWrite(0x12,(s->offB>>8)&0xff);
|
immWrite(0x12,(s->offB>>8)&0xff);
|
||||||
|
|
@ -818,8 +818,9 @@ int DivPlatformYM2610B::dispatch(DivCommand c) {
|
||||||
immWrite(0x15,end>>16);
|
immWrite(0x15,end>>16);
|
||||||
immWrite(0x11,isMuted[c.chan]?0:(chan[c.chan].pan<<6));
|
immWrite(0x11,isMuted[c.chan]?0:(chan[c.chan].pan<<6));
|
||||||
immWrite(0x10,(s->loopStart>=0)?0x90:0x80); // start/repeat
|
immWrite(0x10,(s->loopStart>=0)?0x90:0x80); // start/repeat
|
||||||
chan[c.chan].baseFreq=(((unsigned int)s->rate)<<16)/(chipClock/144);
|
int freq=(65536.0*(double)s->rate)/((double)chipClock/144.0);
|
||||||
chan[c.chan].freqChanged=true;
|
immWrite(0x19,freq&0xff);
|
||||||
|
immWrite(0x1a,(freq>>8)&0xff);
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
@ -975,6 +976,7 @@ int DivPlatformYM2610B::dispatch(DivCommand c) {
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
case DIV_CMD_PITCH: {
|
case DIV_CMD_PITCH: {
|
||||||
|
if (c.chan==15 && !chan[c.chan].furnacePCM) break;
|
||||||
chan[c.chan].pitch=c.value;
|
chan[c.chan].pitch=c.value;
|
||||||
chan[c.chan].freqChanged=true;
|
chan[c.chan].freqChanged=true;
|
||||||
break;
|
break;
|
||||||
|
|
@ -1055,6 +1057,7 @@ int DivPlatformYM2610B::dispatch(DivCommand c) {
|
||||||
iface.sampleBank=sampleBank;
|
iface.sampleBank=sampleBank;
|
||||||
break;
|
break;
|
||||||
case DIV_CMD_LEGATO: {
|
case DIV_CMD_LEGATO: {
|
||||||
|
if (c.chan==15 && !chan[c.chan].furnacePCM) break;
|
||||||
chan[c.chan].baseFreq=NOTE_OPNB(c.chan,c.value);
|
chan[c.chan].baseFreq=NOTE_OPNB(c.chan,c.value);
|
||||||
chan[c.chan].freqChanged=true;
|
chan[c.chan].freqChanged=true;
|
||||||
break;
|
break;
|
||||||
|
|
|
||||||
334
src/engine/platform/zxbeeper.cpp
Normal file
334
src/engine/platform/zxbeeper.cpp
Normal file
|
|
@ -0,0 +1,334 @@
|
||||||
|
/**
|
||||||
|
* Furnace Tracker - multi-system chiptune tracker
|
||||||
|
* Copyright (C) 2021-2022 tildearrow and contributors
|
||||||
|
*
|
||||||
|
* This program is free software; you can redistribute it and/or modify
|
||||||
|
* it under the terms of the GNU General Public License as published by
|
||||||
|
* the Free Software Foundation; either version 2 of the License, or
|
||||||
|
* (at your option) any later version.
|
||||||
|
*
|
||||||
|
* This program is distributed in the hope that it will be useful,
|
||||||
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
|
* GNU General Public License for more details.
|
||||||
|
*
|
||||||
|
* You should have received a copy of the GNU General Public License along
|
||||||
|
* with this program; if not, write to the Free Software Foundation, Inc.,
|
||||||
|
* 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include "zxbeeper.h"
|
||||||
|
#include "../engine.h"
|
||||||
|
#include <math.h>
|
||||||
|
|
||||||
|
#define CHIP_FREQBASE 8192*6
|
||||||
|
|
||||||
|
const char** DivPlatformZXBeeper::getRegisterSheet() {
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
const char* DivPlatformZXBeeper::getEffectName(unsigned char effect) {
|
||||||
|
switch (effect) {
|
||||||
|
case 0x10:
|
||||||
|
return "10xx: Change waveform";
|
||||||
|
break;
|
||||||
|
case 0x11:
|
||||||
|
return "11xx: Toggle noise mode";
|
||||||
|
break;
|
||||||
|
case 0x12:
|
||||||
|
return "12xx: Setup LFO (0: disabled; 1: 1x depth; 2: 16x depth; 3: 256x depth)";
|
||||||
|
break;
|
||||||
|
case 0x13:
|
||||||
|
return "13xx: Set LFO speed";
|
||||||
|
break;
|
||||||
|
case 0x17:
|
||||||
|
return "17xx: Toggle PCM mode";
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
void DivPlatformZXBeeper::acquire(short* bufL, short* bufR, size_t start, size_t len) {
|
||||||
|
for (size_t h=start; h<start+len; h++) {
|
||||||
|
// clock here
|
||||||
|
bool o=false;
|
||||||
|
unsigned short oldPos=chan[curChan].sPosition;
|
||||||
|
|
||||||
|
if (sOffTimer) {
|
||||||
|
sOffTimer--;
|
||||||
|
o=true;
|
||||||
|
}
|
||||||
|
chan[curChan].sPosition+=chan[curChan].freq;
|
||||||
|
if (oldPos>chan[curChan].sPosition) {
|
||||||
|
if (!isMuted[curChan] && chan[curChan].outVol) sOffTimer+=chan[curChan].duty;
|
||||||
|
}
|
||||||
|
if (++curChan>=6) curChan=0;
|
||||||
|
|
||||||
|
bufL[h]=o?16384:0;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void DivPlatformZXBeeper::tick(bool sysTick) {
|
||||||
|
for (int i=0; i<6; i++) {
|
||||||
|
chan[i].std.next();
|
||||||
|
if (chan[i].std.vol.had) {
|
||||||
|
chan[i].outVol=((chan[i].vol&1)*MIN(1,chan[i].std.vol.val));
|
||||||
|
}
|
||||||
|
if (chan[i].std.duty.had) {
|
||||||
|
chan[i].duty=chan[i].std.duty.val;
|
||||||
|
chan[i].freqChanged=true;
|
||||||
|
}
|
||||||
|
if (chan[i].std.arp.had) {
|
||||||
|
if (!chan[i].inPorta) {
|
||||||
|
if (chan[i].std.arp.mode) {
|
||||||
|
chan[i].baseFreq=NOTE_FREQUENCY(chan[i].std.arp.val);
|
||||||
|
} else {
|
||||||
|
chan[i].baseFreq=NOTE_FREQUENCY(chan[i].note+chan[i].std.arp.val);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
chan[i].freqChanged=true;
|
||||||
|
} else {
|
||||||
|
if (chan[i].std.arp.mode && chan[i].std.arp.finished) {
|
||||||
|
chan[i].baseFreq=NOTE_FREQUENCY(chan[i].note);
|
||||||
|
chan[i].freqChanged=true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (chan[i].std.pitch.had) {
|
||||||
|
if (chan[i].std.pitch.mode) {
|
||||||
|
chan[i].pitch2+=chan[i].std.pitch.val;
|
||||||
|
CLAMP_VAR(chan[i].pitch2,-2048,2048);
|
||||||
|
} else {
|
||||||
|
chan[i].pitch2=chan[i].std.pitch.val;
|
||||||
|
}
|
||||||
|
chan[i].freqChanged=true;
|
||||||
|
}
|
||||||
|
if (chan[i].freqChanged || chan[i].keyOn || chan[i].keyOff) {
|
||||||
|
if (chan[i].active) {
|
||||||
|
chan[i].freq=parent->calcFreq(chan[i].baseFreq,chan[i].pitch,false,0,chan[i].pitch2,chipClock,CHIP_FREQBASE);
|
||||||
|
if (chan[i].freq>65535) chan[i].freq=65535;
|
||||||
|
}
|
||||||
|
if (chan[i].keyOn) {
|
||||||
|
//rWrite(16+i*5,0x80);
|
||||||
|
//chWrite(i,0x04,0x80|chan[i].vol);
|
||||||
|
}
|
||||||
|
if (chan[i].keyOff) {
|
||||||
|
chan[i].freq=0;
|
||||||
|
}
|
||||||
|
if (chan[i].keyOn) chan[i].keyOn=false;
|
||||||
|
if (chan[i].keyOff) chan[i].keyOff=false;
|
||||||
|
chan[i].freqChanged=false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
int DivPlatformZXBeeper::dispatch(DivCommand c) {
|
||||||
|
switch (c.cmd) {
|
||||||
|
case DIV_CMD_NOTE_ON: {
|
||||||
|
DivInstrument* ins=parent->getIns(chan[c.chan].ins,DIV_INS_BEEPER);
|
||||||
|
if (c.value!=DIV_NOTE_NULL) {
|
||||||
|
chan[c.chan].baseFreq=NOTE_FREQUENCY(c.value);
|
||||||
|
chan[c.chan].freqChanged=true;
|
||||||
|
chan[c.chan].note=c.value;
|
||||||
|
}
|
||||||
|
chan[c.chan].active=true;
|
||||||
|
chan[c.chan].keyOn=true;
|
||||||
|
chan[c.chan].macroInit(ins);
|
||||||
|
chan[c.chan].insChanged=false;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
case DIV_CMD_NOTE_OFF:
|
||||||
|
chan[c.chan].dacSample=-1;
|
||||||
|
if (dumpWrites) addWrite(0xffff0002+(c.chan<<8),0);
|
||||||
|
chan[c.chan].pcm=false;
|
||||||
|
chan[c.chan].active=false;
|
||||||
|
chan[c.chan].keyOff=true;
|
||||||
|
chan[c.chan].macroInit(NULL);
|
||||||
|
break;
|
||||||
|
case DIV_CMD_NOTE_OFF_ENV:
|
||||||
|
case DIV_CMD_ENV_RELEASE:
|
||||||
|
chan[c.chan].std.release();
|
||||||
|
break;
|
||||||
|
case DIV_CMD_INSTRUMENT:
|
||||||
|
if (chan[c.chan].ins!=c.value || c.value2==1) {
|
||||||
|
chan[c.chan].ins=c.value;
|
||||||
|
chan[c.chan].insChanged=true;
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
case DIV_CMD_VOLUME:
|
||||||
|
if (chan[c.chan].vol!=c.value) {
|
||||||
|
chan[c.chan].vol=c.value;
|
||||||
|
if (!chan[c.chan].std.vol.has) {
|
||||||
|
chan[c.chan].outVol=c.value;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
case DIV_CMD_GET_VOLUME:
|
||||||
|
if (chan[c.chan].std.vol.has) {
|
||||||
|
return chan[c.chan].vol;
|
||||||
|
}
|
||||||
|
return chan[c.chan].outVol;
|
||||||
|
break;
|
||||||
|
case DIV_CMD_PITCH:
|
||||||
|
chan[c.chan].pitch=c.value;
|
||||||
|
chan[c.chan].freqChanged=true;
|
||||||
|
break;
|
||||||
|
case DIV_CMD_NOTE_PORTA: {
|
||||||
|
int destFreq=NOTE_FREQUENCY(c.value2);
|
||||||
|
bool return2=false;
|
||||||
|
if (destFreq>chan[c.chan].baseFreq) {
|
||||||
|
chan[c.chan].baseFreq+=c.value;
|
||||||
|
if (chan[c.chan].baseFreq>=destFreq) {
|
||||||
|
chan[c.chan].baseFreq=destFreq;
|
||||||
|
return2=true;
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
chan[c.chan].baseFreq-=c.value;
|
||||||
|
if (chan[c.chan].baseFreq<=destFreq) {
|
||||||
|
chan[c.chan].baseFreq=destFreq;
|
||||||
|
return2=true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
chan[c.chan].freqChanged=true;
|
||||||
|
if (return2) {
|
||||||
|
chan[c.chan].inPorta=false;
|
||||||
|
return 2;
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
case DIV_CMD_STD_NOISE_MODE:
|
||||||
|
chan[c.chan].duty=c.value;
|
||||||
|
break;
|
||||||
|
case DIV_CMD_SAMPLE_MODE:
|
||||||
|
chan[c.chan].pcm=c.value;
|
||||||
|
break;
|
||||||
|
case DIV_CMD_SAMPLE_BANK:
|
||||||
|
sampleBank=c.value;
|
||||||
|
if (sampleBank>(parent->song.sample.size()/12)) {
|
||||||
|
sampleBank=parent->song.sample.size()/12;
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
case DIV_CMD_LEGATO:
|
||||||
|
chan[c.chan].baseFreq=NOTE_FREQUENCY(c.value+((chan[c.chan].std.arp.will && !chan[c.chan].std.arp.mode)?(chan[c.chan].std.arp.val):(0)));
|
||||||
|
chan[c.chan].freqChanged=true;
|
||||||
|
chan[c.chan].note=c.value;
|
||||||
|
break;
|
||||||
|
case DIV_CMD_PRE_PORTA:
|
||||||
|
if (chan[c.chan].active && c.value2) {
|
||||||
|
if (parent->song.resetMacroOnPorta) chan[c.chan].macroInit(parent->getIns(chan[c.chan].ins,DIV_INS_BEEPER));
|
||||||
|
}
|
||||||
|
chan[c.chan].inPorta=c.value;
|
||||||
|
break;
|
||||||
|
case DIV_CMD_GET_VOLMAX:
|
||||||
|
return 1;
|
||||||
|
break;
|
||||||
|
case DIV_ALWAYS_SET_VOLUME:
|
||||||
|
return 1;
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
void DivPlatformZXBeeper::muteChannel(int ch, bool mute) {
|
||||||
|
isMuted[ch]=mute;
|
||||||
|
}
|
||||||
|
|
||||||
|
void DivPlatformZXBeeper::forceIns() {
|
||||||
|
for (int i=0; i<6; i++) {
|
||||||
|
chan[i].insChanged=true;
|
||||||
|
chan[i].freqChanged=true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void* DivPlatformZXBeeper::getChanState(int ch) {
|
||||||
|
return &chan[ch];
|
||||||
|
}
|
||||||
|
|
||||||
|
DivDispatchOscBuffer* DivPlatformZXBeeper::getOscBuffer(int ch) {
|
||||||
|
return oscBuf[ch];
|
||||||
|
}
|
||||||
|
|
||||||
|
unsigned char* DivPlatformZXBeeper::getRegisterPool() {
|
||||||
|
ulaOut=sOffTimer?0x10:0x08;
|
||||||
|
return &ulaOut;
|
||||||
|
}
|
||||||
|
|
||||||
|
int DivPlatformZXBeeper::getRegisterPoolSize() {
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
void DivPlatformZXBeeper::reset() {
|
||||||
|
while (!writes.empty()) writes.pop();
|
||||||
|
memset(regPool,0,128);
|
||||||
|
for (int i=0; i<6; i++) {
|
||||||
|
chan[i]=DivPlatformZXBeeper::Channel();
|
||||||
|
chan[i].std.setEngine(parent);
|
||||||
|
}
|
||||||
|
if (dumpWrites) {
|
||||||
|
addWrite(0xffffffff,0);
|
||||||
|
}
|
||||||
|
lastPan=0xff;
|
||||||
|
memset(tempL,0,32*sizeof(int));
|
||||||
|
memset(tempR,0,32*sizeof(int));
|
||||||
|
cycles=0;
|
||||||
|
curChan=0;
|
||||||
|
sOffTimer=0;
|
||||||
|
sampleBank=0;
|
||||||
|
ulaOut=0;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool DivPlatformZXBeeper::keyOffAffectsArp(int ch) {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
void DivPlatformZXBeeper::notifyWaveChange(int wave) {
|
||||||
|
}
|
||||||
|
|
||||||
|
void DivPlatformZXBeeper::notifyInsDeletion(void* ins) {
|
||||||
|
for (int i=0; i<6; i++) {
|
||||||
|
chan[i].std.notifyInsDeletion((DivInstrument*)ins);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void DivPlatformZXBeeper::setFlags(unsigned int flags) {
|
||||||
|
if (flags&1) { // technically there is no PAL PC Engine but oh well...
|
||||||
|
chipClock=COLOR_PAL*4.0/5.0;
|
||||||
|
} else {
|
||||||
|
chipClock=COLOR_NTSC;
|
||||||
|
}
|
||||||
|
rate=chipClock/4;
|
||||||
|
for (int i=0; i<6; i++) {
|
||||||
|
oscBuf[i]->rate=rate;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void DivPlatformZXBeeper::poke(unsigned int addr, unsigned short val) {
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
void DivPlatformZXBeeper::poke(std::vector<DivRegWrite>& wlist) {
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
int DivPlatformZXBeeper::init(DivEngine* p, int channels, int sugRate, unsigned int flags) {
|
||||||
|
parent=p;
|
||||||
|
dumpWrites=false;
|
||||||
|
skipRegisterWrites=false;
|
||||||
|
for (int i=0; i<6; i++) {
|
||||||
|
isMuted[i]=false;
|
||||||
|
oscBuf[i]=new DivDispatchOscBuffer;
|
||||||
|
}
|
||||||
|
setFlags(flags);
|
||||||
|
reset();
|
||||||
|
return 6;
|
||||||
|
}
|
||||||
|
|
||||||
|
void DivPlatformZXBeeper::quit() {
|
||||||
|
for (int i=0; i<6; i++) {
|
||||||
|
delete oscBuf[i];
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
DivPlatformZXBeeper::~DivPlatformZXBeeper() {
|
||||||
|
}
|
||||||
108
src/engine/platform/zxbeeper.h
Normal file
108
src/engine/platform/zxbeeper.h
Normal file
|
|
@ -0,0 +1,108 @@
|
||||||
|
/**
|
||||||
|
* Furnace Tracker - multi-system chiptune tracker
|
||||||
|
* Copyright (C) 2021-2022 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 _ZXBEEPER_H
|
||||||
|
#define _ZXBEEPER_H
|
||||||
|
|
||||||
|
#include "../dispatch.h"
|
||||||
|
#include <queue>
|
||||||
|
#include "../macroInt.h"
|
||||||
|
|
||||||
|
class DivPlatformZXBeeper: public DivDispatch {
|
||||||
|
struct Channel {
|
||||||
|
int freq, baseFreq, pitch, pitch2, note;
|
||||||
|
int dacPeriod, dacRate;
|
||||||
|
unsigned int dacPos;
|
||||||
|
int dacSample, ins;
|
||||||
|
bool active, insChanged, freqChanged, keyOn, keyOff, inPorta, noise, pcm, furnaceDac;
|
||||||
|
signed char vol, outVol;
|
||||||
|
unsigned short sPosition;
|
||||||
|
unsigned char duty;
|
||||||
|
DivMacroInt std;
|
||||||
|
void macroInit(DivInstrument* which) {
|
||||||
|
std.init(which);
|
||||||
|
pitch2=0;
|
||||||
|
}
|
||||||
|
Channel():
|
||||||
|
freq(0),
|
||||||
|
baseFreq(0),
|
||||||
|
pitch(0),
|
||||||
|
pitch2(0),
|
||||||
|
note(0),
|
||||||
|
dacPeriod(0),
|
||||||
|
dacRate(0),
|
||||||
|
dacPos(0),
|
||||||
|
dacSample(-1),
|
||||||
|
ins(-1),
|
||||||
|
active(false),
|
||||||
|
insChanged(true),
|
||||||
|
freqChanged(false),
|
||||||
|
keyOn(false),
|
||||||
|
keyOff(false),
|
||||||
|
inPorta(false),
|
||||||
|
noise(false),
|
||||||
|
pcm(false),
|
||||||
|
furnaceDac(false),
|
||||||
|
vol(1),
|
||||||
|
outVol(1),
|
||||||
|
sPosition(0),
|
||||||
|
duty(64) {}
|
||||||
|
};
|
||||||
|
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;
|
||||||
|
int tempL[32];
|
||||||
|
int tempR[32];
|
||||||
|
unsigned char sampleBank, lfoMode, lfoSpeed;
|
||||||
|
unsigned char regPool[128];
|
||||||
|
friend void putDispatchChan(void*,int,int);
|
||||||
|
public:
|
||||||
|
void acquire(short* bufL, short* bufR, size_t start, size_t len);
|
||||||
|
int dispatch(DivCommand c);
|
||||||
|
void* getChanState(int chan);
|
||||||
|
DivDispatchOscBuffer* getOscBuffer(int chan);
|
||||||
|
unsigned char* getRegisterPool();
|
||||||
|
int getRegisterPoolSize();
|
||||||
|
void reset();
|
||||||
|
void forceIns();
|
||||||
|
void tick(bool sysTick=true);
|
||||||
|
void muteChannel(int ch, bool mute);
|
||||||
|
bool keyOffAffectsArp(int ch);
|
||||||
|
void setFlags(unsigned int flags);
|
||||||
|
void notifyWaveChange(int wave);
|
||||||
|
void notifyInsDeletion(void* ins);
|
||||||
|
void poke(unsigned int addr, unsigned short val);
|
||||||
|
void poke(std::vector<DivRegWrite>& wlist);
|
||||||
|
const char** getRegisterSheet();
|
||||||
|
const char* getEffectName(unsigned char effect);
|
||||||
|
int init(DivEngine* parent, int channels, int sugRate, unsigned int flags);
|
||||||
|
void quit();
|
||||||
|
~DivPlatformZXBeeper();
|
||||||
|
};
|
||||||
|
|
||||||
|
#endif
|
||||||
|
|
@ -65,7 +65,9 @@ enum DivSystem {
|
||||||
DIV_SYSTEM_MMC5,
|
DIV_SYSTEM_MMC5,
|
||||||
DIV_SYSTEM_N163,
|
DIV_SYSTEM_N163,
|
||||||
DIV_SYSTEM_OPN,
|
DIV_SYSTEM_OPN,
|
||||||
|
DIV_SYSTEM_OPN_EXT,
|
||||||
DIV_SYSTEM_PC98,
|
DIV_SYSTEM_PC98,
|
||||||
|
DIV_SYSTEM_PC98_EXT,
|
||||||
DIV_SYSTEM_OPL,
|
DIV_SYSTEM_OPL,
|
||||||
DIV_SYSTEM_OPL2,
|
DIV_SYSTEM_OPL2,
|
||||||
DIV_SYSTEM_OPL3,
|
DIV_SYSTEM_OPL3,
|
||||||
|
|
|
||||||
|
|
@ -734,6 +734,7 @@ void DivEngine::registerSystems() {
|
||||||
|
|
||||||
sysDefs[DIV_SYSTEM_YMU759]=new DivSysDef(
|
sysDefs[DIV_SYSTEM_YMU759]=new DivSysDef(
|
||||||
"Yamaha YMU759 (MA-2)", NULL, 0x01, 0x01, 17, true, false, 0, false,
|
"Yamaha YMU759 (MA-2)", NULL, 0x01, 0x01, 17, true, false, 0, false,
|
||||||
|
"a chip which found its way inside mobile phones in the 2000's.\nas proprietary as it is, it passed away after losing to MP3 in the mobile hardware battle.",
|
||||||
{"Channel 1", "Channel 2", "Channel 3", "Channel 4", "Channel 5", "Channel 6", "Channel 7", "Channel 8", "Channel 9", "Channel 10", "Channel 11", "Channel 12", "Channel 13", "Channel 14", "Channel 15", "Channel 16", "PCM" }, // name
|
{"Channel 1", "Channel 2", "Channel 3", "Channel 4", "Channel 5", "Channel 6", "Channel 7", "Channel 8", "Channel 9", "Channel 10", "Channel 11", "Channel 12", "Channel 13", "Channel 14", "Channel 15", "Channel 16", "PCM" }, // name
|
||||||
{"1", "2", "3", "4", "5", "6", "7", "8", "9", "10", "11", "12", "13", "14", "15", "16", "PCM" }, // short
|
{"1", "2", "3", "4", "5", "6", "7", "8", "9", "10", "11", "12", "13", "14", "15", "16", "PCM" }, // short
|
||||||
{DIV_CH_FM, DIV_CH_FM, DIV_CH_FM, DIV_CH_FM, DIV_CH_FM, DIV_CH_FM, DIV_CH_FM, DIV_CH_FM, DIV_CH_FM, DIV_CH_FM, DIV_CH_FM, DIV_CH_FM, DIV_CH_FM, DIV_CH_FM, DIV_CH_FM, DIV_CH_FM, DIV_CH_PCM }, // type
|
{DIV_CH_FM, DIV_CH_FM, DIV_CH_FM, DIV_CH_FM, DIV_CH_FM, DIV_CH_FM, DIV_CH_FM, DIV_CH_FM, DIV_CH_FM, DIV_CH_FM, DIV_CH_FM, DIV_CH_FM, DIV_CH_FM, DIV_CH_FM, DIV_CH_FM, DIV_CH_FM, DIV_CH_PCM }, // type
|
||||||
|
|
@ -742,16 +743,19 @@ void DivEngine::registerSystems() {
|
||||||
|
|
||||||
sysDefs[DIV_SYSTEM_GENESIS]=new DivSysDef(
|
sysDefs[DIV_SYSTEM_GENESIS]=new DivSysDef(
|
||||||
"Sega Genesis/Mega Drive", "セガメガドライブ", 0x02, 0x02, 10, true, true, 0, true,
|
"Sega Genesis/Mega Drive", "セガメガドライブ", 0x02, 0x02, 10, true, true, 0, true,
|
||||||
|
"<COMPOUND SYSTEM!>",
|
||||||
{}, {}, {}, {}
|
{}, {}, {}, {}
|
||||||
);
|
);
|
||||||
|
|
||||||
sysDefs[DIV_SYSTEM_GENESIS_EXT]=new DivSysDef(
|
sysDefs[DIV_SYSTEM_GENESIS_EXT]=new DivSysDef(
|
||||||
"Sega Genesis Extended Channel 3", NULL, 0x42, 0x42, 13, true, true, 0, true,
|
"Sega Genesis Extended Channel 3", NULL, 0x42, 0x42, 13, true, true, 0, true,
|
||||||
|
"<COMPOUND SYSTEM!>",
|
||||||
{}, {}, {}, {}
|
{}, {}, {}, {}
|
||||||
);
|
);
|
||||||
|
|
||||||
sysDefs[DIV_SYSTEM_SMS]=new DivSysDef(
|
sysDefs[DIV_SYSTEM_SMS]=new DivSysDef(
|
||||||
"TI SN76489", NULL, 0x03, 0x03, 4, false, true, 0x150, false,
|
"TI SN76489", NULL, 0x03, 0x03, 4, false, true, 0x150, false,
|
||||||
|
"a square/noise sound chip found on the Sega Master System, ColecoVision, Tandy, TI's own 99/4A and a few other places.",
|
||||||
{"Square 1", "Square 2", "Square 3", "Noise"},
|
{"Square 1", "Square 2", "Square 3", "Noise"},
|
||||||
{"S1", "S2", "S3", "NO"},
|
{"S1", "S2", "S3", "NO"},
|
||||||
{DIV_CH_PULSE, DIV_CH_PULSE, DIV_CH_PULSE, DIV_CH_NOISE},
|
{DIV_CH_PULSE, DIV_CH_PULSE, DIV_CH_PULSE, DIV_CH_NOISE},
|
||||||
|
|
@ -771,11 +775,13 @@ void DivEngine::registerSystems() {
|
||||||
|
|
||||||
sysDefs[DIV_SYSTEM_SMS_OPLL]=new DivSysDef(
|
sysDefs[DIV_SYSTEM_SMS_OPLL]=new DivSysDef(
|
||||||
"Sega Master System + FM Expansion", NULL, 0x43, 0x43, 13, true, true, 0, true,
|
"Sega Master System + FM Expansion", NULL, 0x43, 0x43, 13, true, true, 0, true,
|
||||||
|
"<COMPOUND SYSTEM!>",
|
||||||
{}, {}, {}, {}
|
{}, {}, {}, {}
|
||||||
);
|
);
|
||||||
|
|
||||||
sysDefs[DIV_SYSTEM_GB]=new DivSysDef(
|
sysDefs[DIV_SYSTEM_GB]=new DivSysDef(
|
||||||
"Game Boy", NULL, 0x04, 0x04, 4, false, true, 0x161, false,
|
"Game Boy", NULL, 0x04, 0x04, 4, false, true, 0x161, false,
|
||||||
|
"the most popular portable game console of the era.",
|
||||||
{"Pulse 1", "Pulse 2", "Wavetable", "Noise"},
|
{"Pulse 1", "Pulse 2", "Wavetable", "Noise"},
|
||||||
{"S1", "S2", "WA", "NO"},
|
{"S1", "S2", "WA", "NO"},
|
||||||
{DIV_CH_PULSE, DIV_CH_PULSE, DIV_CH_WAVE, DIV_CH_NOISE},
|
{DIV_CH_PULSE, DIV_CH_PULSE, DIV_CH_WAVE, DIV_CH_NOISE},
|
||||||
|
|
@ -804,6 +810,7 @@ void DivEngine::registerSystems() {
|
||||||
|
|
||||||
sysDefs[DIV_SYSTEM_PCE]=new DivSysDef(
|
sysDefs[DIV_SYSTEM_PCE]=new DivSysDef(
|
||||||
"PC Engine/TurboGrafx-16", NULL, 0x05, 0x05, 6, false, true, 0x161, false,
|
"PC Engine/TurboGrafx-16", NULL, 0x05, 0x05, 6, false, true, 0x161, false,
|
||||||
|
"an '80's game console with a wavetable sound chip, popular in Japan.",
|
||||||
{"Channel 1", "Channel 2", "Channel 3", "Channel 4", "Channel 5", "Channel 6"},
|
{"Channel 1", "Channel 2", "Channel 3", "Channel 4", "Channel 5", "Channel 6"},
|
||||||
{"CH1", "CH2", "CH3", "CH4", "CH5", "CH6"},
|
{"CH1", "CH2", "CH3", "CH4", "CH5", "CH6"},
|
||||||
{DIV_CH_WAVE, DIV_CH_WAVE, DIV_CH_WAVE, DIV_CH_WAVE, DIV_CH_WAVE, DIV_CH_WAVE},
|
{DIV_CH_WAVE, DIV_CH_WAVE, DIV_CH_WAVE, DIV_CH_WAVE, DIV_CH_WAVE, DIV_CH_WAVE},
|
||||||
|
|
@ -835,6 +842,7 @@ void DivEngine::registerSystems() {
|
||||||
|
|
||||||
sysDefs[DIV_SYSTEM_NES]=new DivSysDef(
|
sysDefs[DIV_SYSTEM_NES]=new DivSysDef(
|
||||||
"NES (Ricoh 2A03)", NULL, 0x06, 0x06, 5, false, true, 0x161, false,
|
"NES (Ricoh 2A03)", NULL, 0x06, 0x06, 5, false, true, 0x161, false,
|
||||||
|
"also known as Famicom in Japan, it's the most well-known game console of the '80's.",
|
||||||
{"Pulse 1", "Pulse 2", "Triangle", "Noise", "PCM"},
|
{"Pulse 1", "Pulse 2", "Triangle", "Noise", "PCM"},
|
||||||
{"S1", "S2", "TR", "NO", "PCM"},
|
{"S1", "S2", "TR", "NO", "PCM"},
|
||||||
{DIV_CH_PULSE, DIV_CH_PULSE, DIV_CH_WAVE, DIV_CH_NOISE, DIV_CH_PCM},
|
{DIV_CH_PULSE, DIV_CH_PULSE, DIV_CH_WAVE, DIV_CH_NOISE, DIV_CH_PCM},
|
||||||
|
|
@ -866,16 +874,19 @@ void DivEngine::registerSystems() {
|
||||||
|
|
||||||
sysDefs[DIV_SYSTEM_NES_VRC7]=new DivSysDef(
|
sysDefs[DIV_SYSTEM_NES_VRC7]=new DivSysDef(
|
||||||
"NES + Konami VRC7", NULL, 0x46, 0x46, 11, true, true, 0, true,
|
"NES + Konami VRC7", NULL, 0x46, 0x46, 11, true, true, 0, true,
|
||||||
|
"<COMPOUND SYSTEM!>",
|
||||||
{}, {}, {}, {}
|
{}, {}, {}, {}
|
||||||
);
|
);
|
||||||
|
|
||||||
sysDefs[DIV_SYSTEM_NES_FDS]=new DivSysDef(
|
sysDefs[DIV_SYSTEM_NES_FDS]=new DivSysDef(
|
||||||
"Famicom Disk System", NULL, 0, 0x86, 6, false, true, 0, true,
|
"Famicom Disk System", NULL, 0, 0x86, 6, false, true, 0, true,
|
||||||
|
"<COMPOUND SYSTEM!>",
|
||||||
{}, {}, {}, {}
|
{}, {}, {}, {}
|
||||||
);
|
);
|
||||||
|
|
||||||
sysDefs[DIV_SYSTEM_C64_6581]=new DivSysDef(
|
sysDefs[DIV_SYSTEM_C64_6581]=new DivSysDef(
|
||||||
"Commodore 64 (6581)", NULL, 0x47, 0x47, 3, false, true, 0, false,
|
"Commodore 64 (6581)", NULL, 0x47, 0x47, 3, false, true, 0, false,
|
||||||
|
"this computer is powered by the SID chip, which had synthesizer features like a filter and ADSR.",
|
||||||
{"Channel 1", "Channel 2", "Channel 3"},
|
{"Channel 1", "Channel 2", "Channel 3"},
|
||||||
{"CH1", "CH2", "CH3"},
|
{"CH1", "CH2", "CH3"},
|
||||||
{DIV_CH_NOISE, DIV_CH_NOISE, DIV_CH_NOISE},
|
{DIV_CH_NOISE, DIV_CH_NOISE, DIV_CH_NOISE},
|
||||||
|
|
@ -887,6 +898,7 @@ void DivEngine::registerSystems() {
|
||||||
|
|
||||||
sysDefs[DIV_SYSTEM_C64_8580]=new DivSysDef(
|
sysDefs[DIV_SYSTEM_C64_8580]=new DivSysDef(
|
||||||
"Commodore 64 (8580)", NULL, 0x07, 0x07, 3, false, true, 0, false,
|
"Commodore 64 (8580)", NULL, 0x07, 0x07, 3, false, true, 0, false,
|
||||||
|
"this computer is powered by the SID chip, which had synthesizer features like a filter and ADSR.\nthis is the newer revision of the chip.",
|
||||||
{"Channel 1", "Channel 2", "Channel 3"},
|
{"Channel 1", "Channel 2", "Channel 3"},
|
||||||
{"CH1", "CH2", "CH3"},
|
{"CH1", "CH2", "CH3"},
|
||||||
{DIV_CH_NOISE, DIV_CH_NOISE, DIV_CH_NOISE},
|
{DIV_CH_NOISE, DIV_CH_NOISE, DIV_CH_NOISE},
|
||||||
|
|
@ -898,6 +910,7 @@ void DivEngine::registerSystems() {
|
||||||
|
|
||||||
sysDefs[DIV_SYSTEM_ARCADE]=new DivSysDef(
|
sysDefs[DIV_SYSTEM_ARCADE]=new DivSysDef(
|
||||||
"DefleCade", NULL, 0x08, 0x08, 13, true, false, 0, true,
|
"DefleCade", NULL, 0x08, 0x08, 13, true, false, 0, true,
|
||||||
|
"<COMPOUND SYSTEM!>",
|
||||||
{}, {}, {}, {}
|
{}, {}, {}, {}
|
||||||
);
|
);
|
||||||
|
|
||||||
|
|
@ -914,6 +927,7 @@ void DivEngine::registerSystems() {
|
||||||
|
|
||||||
sysDefs[DIV_SYSTEM_YM2610]=new DivSysDef(
|
sysDefs[DIV_SYSTEM_YM2610]=new DivSysDef(
|
||||||
"Neo Geo CD", NULL, 0x09, 0x09, 13, true, true, 0x151, false,
|
"Neo Geo CD", NULL, 0x09, 0x09, 13, true, true, 0x151, false,
|
||||||
|
"like Neo Geo, but lacking the ADPCM-B channel since they couldn't connect the pins.",
|
||||||
{"FM 1", "FM 2", "FM 3", "FM 4", "PSG 1", "PSG 2", "PSG 3", "ADPCM-A 1", "ADPCM-A 2", "ADPCM-A 3", "ADPCM-A 4", "ADPCM-A 5", "ADPCM-A 6"},
|
{"FM 1", "FM 2", "FM 3", "FM 4", "PSG 1", "PSG 2", "PSG 3", "ADPCM-A 1", "ADPCM-A 2", "ADPCM-A 3", "ADPCM-A 4", "ADPCM-A 5", "ADPCM-A 6"},
|
||||||
{"F1", "F2", "F3", "F4", "S1", "S2", "S3", "P1", "P2", "P3", "P4", "P5", "P6"},
|
{"F1", "F2", "F3", "F4", "S1", "S2", "S3", "P1", "P2", "P3", "P4", "P5", "P6"},
|
||||||
{DIV_CH_FM, DIV_CH_FM, DIV_CH_FM, DIV_CH_FM, DIV_CH_PULSE, DIV_CH_PULSE, DIV_CH_PULSE, DIV_CH_PCM, DIV_CH_PCM, DIV_CH_PCM, DIV_CH_PCM, DIV_CH_PCM, DIV_CH_PCM},
|
{DIV_CH_FM, DIV_CH_FM, DIV_CH_FM, DIV_CH_FM, DIV_CH_PULSE, DIV_CH_PULSE, DIV_CH_PULSE, DIV_CH_PCM, DIV_CH_PCM, DIV_CH_PCM, DIV_CH_PCM, DIV_CH_PCM, DIV_CH_PCM},
|
||||||
|
|
@ -925,6 +939,7 @@ void DivEngine::registerSystems() {
|
||||||
|
|
||||||
sysDefs[DIV_SYSTEM_YM2610_EXT]=new DivSysDef(
|
sysDefs[DIV_SYSTEM_YM2610_EXT]=new DivSysDef(
|
||||||
"Neo Geo CD Extended Channel 2", NULL, 0x49, 0x49, 16, true, true, 0x151, false,
|
"Neo Geo CD Extended Channel 2", NULL, 0x49, 0x49, 16, true, true, 0x151, false,
|
||||||
|
"like Neo Geo, but lacking the ADPCM-B channel since they couldn't connect the pins.\nthis one is in Extended Channel mode, which turns the second FM channel into four operators with independent notes/frequencies.",
|
||||||
{"FM 1", "FM 2 OP1", "FM 2 OP2", "FM 2 OP3", "FM 2 OP4", "FM 3", "FM 4", "PSG 1", "PSG 2", "PSG 3", "ADPCM-A 1", "ADPCM-A 2", "ADPCM-A 3", "ADPCM-A 4", "ADPCM-A 5", "ADPCM-A 6"},
|
{"FM 1", "FM 2 OP1", "FM 2 OP2", "FM 2 OP3", "FM 2 OP4", "FM 3", "FM 4", "PSG 1", "PSG 2", "PSG 3", "ADPCM-A 1", "ADPCM-A 2", "ADPCM-A 3", "ADPCM-A 4", "ADPCM-A 5", "ADPCM-A 6"},
|
||||||
{"F1", "O1", "O2", "O3", "O4", "F3", "F4", "S1", "S2", "S3", "P1", "P2", "P3", "P4", "P5", "P6"},
|
{"F1", "O1", "O2", "O3", "O4", "F3", "F4", "S1", "S2", "S3", "P1", "P2", "P3", "P4", "P5", "P6"},
|
||||||
{DIV_CH_FM, DIV_CH_OP, DIV_CH_OP, DIV_CH_OP, DIV_CH_OP, DIV_CH_FM, DIV_CH_FM, DIV_CH_PULSE, DIV_CH_PULSE, DIV_CH_PULSE, DIV_CH_PCM, DIV_CH_PCM, DIV_CH_PCM, DIV_CH_PCM, DIV_CH_PCM, DIV_CH_PCM},
|
{DIV_CH_FM, DIV_CH_OP, DIV_CH_OP, DIV_CH_OP, DIV_CH_OP, DIV_CH_FM, DIV_CH_FM, DIV_CH_PULSE, DIV_CH_PULSE, DIV_CH_PULSE, DIV_CH_PCM, DIV_CH_PCM, DIV_CH_PCM, DIV_CH_PCM, DIV_CH_PCM, DIV_CH_PCM},
|
||||||
|
|
@ -936,6 +951,7 @@ void DivEngine::registerSystems() {
|
||||||
|
|
||||||
sysDefs[DIV_SYSTEM_AY8910]=new DivSysDef(
|
sysDefs[DIV_SYSTEM_AY8910]=new DivSysDef(
|
||||||
"AY-3-8910", NULL, 0x80, 0, 3, false, true, 0x151, false,
|
"AY-3-8910", NULL, 0x80, 0, 3, false, true, 0x151, false,
|
||||||
|
"this chip is everywhere! ZX Spectrum, MSX, Amstrad CPC, Intellivision, Vectrex...\nthe discovery of envelope bass helped it beat the SN76489 with ease.",
|
||||||
{"PSG 1", "PSG 2", "PSG 3"},
|
{"PSG 1", "PSG 2", "PSG 3"},
|
||||||
{"S1", "S2", "S3"},
|
{"S1", "S2", "S3"},
|
||||||
{DIV_CH_PULSE, DIV_CH_PULSE, DIV_CH_PULSE},
|
{DIV_CH_PULSE, DIV_CH_PULSE, DIV_CH_PULSE},
|
||||||
|
|
@ -947,6 +963,7 @@ void DivEngine::registerSystems() {
|
||||||
|
|
||||||
sysDefs[DIV_SYSTEM_AMIGA]=new DivSysDef(
|
sysDefs[DIV_SYSTEM_AMIGA]=new DivSysDef(
|
||||||
"Amiga", NULL, 0x81, 0, 4, false, true, 0, false,
|
"Amiga", NULL, 0x81, 0, 4, false, true, 0, false,
|
||||||
|
"a computer from the '80's with full sampling capabilities, giving it a sound ahead of its time.",
|
||||||
{"Channel 1", "Channel 2", "Channel 3", "Channel 4"},
|
{"Channel 1", "Channel 2", "Channel 3", "Channel 4"},
|
||||||
{"CH1", "CH2", "CH3", "CH4"},
|
{"CH1", "CH2", "CH3", "CH4"},
|
||||||
{DIV_CH_PCM, DIV_CH_PCM, DIV_CH_PCM, DIV_CH_PCM},
|
{DIV_CH_PCM, DIV_CH_PCM, DIV_CH_PCM, DIV_CH_PCM},
|
||||||
|
|
@ -973,6 +990,7 @@ void DivEngine::registerSystems() {
|
||||||
|
|
||||||
sysDefs[DIV_SYSTEM_YM2151]=new DivSysDef(
|
sysDefs[DIV_SYSTEM_YM2151]=new DivSysDef(
|
||||||
"Yamaha YM2151 (OPM)", NULL, 0x82, 0, 8, true, false, 0x150, false,
|
"Yamaha YM2151 (OPM)", NULL, 0x82, 0, 8, true, false, 0x150, false,
|
||||||
|
"this was Yamaha's first integrated FM chip.\nit was used in several synthesizers, computers and arcade boards.",
|
||||||
{"FM 1", "FM 2", "FM 3", "FM 4", "FM 5", "FM 6", "FM 7", "FM 8"},
|
{"FM 1", "FM 2", "FM 3", "FM 4", "FM 5", "FM 6", "FM 7", "FM 8"},
|
||||||
{"F1", "F2", "F3", "F4", "F5", "F6", "F7", "F8"},
|
{"F1", "F2", "F3", "F4", "F5", "F6", "F7", "F8"},
|
||||||
{DIV_CH_FM, DIV_CH_FM, DIV_CH_FM, DIV_CH_FM, DIV_CH_FM, DIV_CH_FM, DIV_CH_FM, DIV_CH_FM},
|
{DIV_CH_FM, DIV_CH_FM, DIV_CH_FM, DIV_CH_FM, DIV_CH_FM, DIV_CH_FM, DIV_CH_FM, DIV_CH_FM},
|
||||||
|
|
@ -998,6 +1016,7 @@ void DivEngine::registerSystems() {
|
||||||
|
|
||||||
sysDefs[DIV_SYSTEM_YM2612]=new DivSysDef(
|
sysDefs[DIV_SYSTEM_YM2612]=new DivSysDef(
|
||||||
"Yamaha YM2612 (OPN2)", NULL, 0x83, 0, 6, true, false, 0x150, false,
|
"Yamaha YM2612 (OPN2)", NULL, 0x83, 0, 6, true, false, 0x150, false,
|
||||||
|
"this chip is mostly known for being in the Sega Genesis (but it also was on the FM Towns computer).",
|
||||||
{"FM 1", "FM 2", "FM 3", "FM 4", "FM 5", "FM 6"},
|
{"FM 1", "FM 2", "FM 3", "FM 4", "FM 5", "FM 6"},
|
||||||
{"F1", "F2", "F3", "F4", "F5", "F6"},
|
{"F1", "F2", "F3", "F4", "F5", "F6"},
|
||||||
{DIV_CH_FM, DIV_CH_FM, DIV_CH_FM, DIV_CH_FM, DIV_CH_FM, DIV_CH_FM},
|
{DIV_CH_FM, DIV_CH_FM, DIV_CH_FM, DIV_CH_FM, DIV_CH_FM, DIV_CH_FM},
|
||||||
|
|
@ -1009,6 +1028,7 @@ void DivEngine::registerSystems() {
|
||||||
|
|
||||||
sysDefs[DIV_SYSTEM_TIA]=new DivSysDef(
|
sysDefs[DIV_SYSTEM_TIA]=new DivSysDef(
|
||||||
"Atari 2600", NULL, 0x84, 0, 2, false, true, 0, false,
|
"Atari 2600", NULL, 0x84, 0, 2, false, true, 0, false,
|
||||||
|
"it's a challenge to make music on this chip which barely has musical capabilities...",
|
||||||
{"Channel 1", "Channel 2"},
|
{"Channel 1", "Channel 2"},
|
||||||
{"CH1", "CH2"},
|
{"CH1", "CH2"},
|
||||||
{DIV_CH_WAVE, DIV_CH_WAVE},
|
{DIV_CH_WAVE, DIV_CH_WAVE},
|
||||||
|
|
@ -1029,6 +1049,7 @@ void DivEngine::registerSystems() {
|
||||||
|
|
||||||
sysDefs[DIV_SYSTEM_SAA1099]=new DivSysDef(
|
sysDefs[DIV_SYSTEM_SAA1099]=new DivSysDef(
|
||||||
"Philips SAA1099", NULL, 0x97, 0, 6, false, true, 0x171, false,
|
"Philips SAA1099", NULL, 0x97, 0, 6, false, true, 0x171, false,
|
||||||
|
"supposedly an upgrade from the AY-3-8910, this was present on the Creative Music System (Game Blaster) and SAM Coupé.",
|
||||||
{"PSG 1", "PSG 2", "PSG 3", "PSG 4", "PSG 5", "PSG 6"},
|
{"PSG 1", "PSG 2", "PSG 3", "PSG 4", "PSG 5", "PSG 6"},
|
||||||
{"S1", "S2", "S3", "S4", "S5", "S6"},
|
{"S1", "S2", "S3", "S4", "S5", "S6"},
|
||||||
{DIV_CH_PULSE, DIV_CH_PULSE, DIV_CH_PULSE, DIV_CH_PULSE, DIV_CH_PULSE, DIV_CH_PULSE},
|
{DIV_CH_PULSE, DIV_CH_PULSE, DIV_CH_PULSE, DIV_CH_PULSE, DIV_CH_PULSE, DIV_CH_PULSE},
|
||||||
|
|
@ -1055,6 +1076,7 @@ void DivEngine::registerSystems() {
|
||||||
|
|
||||||
sysDefs[DIV_SYSTEM_AY8930]=new DivSysDef(
|
sysDefs[DIV_SYSTEM_AY8930]=new DivSysDef(
|
||||||
"Microchip AY8930", NULL, 0x9a, 0, 3, false, true, 0x151, false,
|
"Microchip AY8930", NULL, 0x9a, 0, 3, false, true, 0x151, false,
|
||||||
|
"an improved version of the AY-3-8910 with a bigger frequency range, duty cycles, configurable noise and per-channel envelopes!",
|
||||||
{"PSG 1", "PSG 2", "PSG 3"},
|
{"PSG 1", "PSG 2", "PSG 3"},
|
||||||
{"S1", "S2", "S3"},
|
{"S1", "S2", "S3"},
|
||||||
{DIV_CH_PULSE, DIV_CH_PULSE, DIV_CH_PULSE},
|
{DIV_CH_PULSE, DIV_CH_PULSE, DIV_CH_PULSE},
|
||||||
|
|
@ -1077,6 +1099,7 @@ void DivEngine::registerSystems() {
|
||||||
|
|
||||||
sysDefs[DIV_SYSTEM_VIC20]=new DivSysDef(
|
sysDefs[DIV_SYSTEM_VIC20]=new DivSysDef(
|
||||||
"Commodore VIC-20", NULL, 0x85, 0, 4, false, true, 0, false,
|
"Commodore VIC-20", NULL, 0x85, 0, 4, false, true, 0, false,
|
||||||
|
"Commodore's successor to the PET.\nits square wave channels are more than just square...",
|
||||||
{"Low", "Mid", "High", "Noise"},
|
{"Low", "Mid", "High", "Noise"},
|
||||||
{"LO", "MID", "HI", "NO"},
|
{"LO", "MID", "HI", "NO"},
|
||||||
{DIV_CH_PULSE, DIV_CH_PULSE, DIV_CH_PULSE, DIV_CH_NOISE},
|
{DIV_CH_PULSE, DIV_CH_PULSE, DIV_CH_PULSE, DIV_CH_NOISE},
|
||||||
|
|
@ -1087,6 +1110,7 @@ void DivEngine::registerSystems() {
|
||||||
|
|
||||||
sysDefs[DIV_SYSTEM_PET]=new DivSysDef(
|
sysDefs[DIV_SYSTEM_PET]=new DivSysDef(
|
||||||
"Commodore PET", NULL, 0x86, 0, 1, false, true, 0, false,
|
"Commodore PET", NULL, 0x86, 0, 1, false, true, 0, false,
|
||||||
|
"one channel of 1-bit wavetable which is better (and worse) than the PC Speaker.",
|
||||||
{"Wave"},
|
{"Wave"},
|
||||||
{"PET"},
|
{"PET"},
|
||||||
{DIV_CH_PULSE},
|
{DIV_CH_PULSE},
|
||||||
|
|
@ -1097,6 +1121,7 @@ void DivEngine::registerSystems() {
|
||||||
|
|
||||||
sysDefs[DIV_SYSTEM_SNES]=new DivSysDef(
|
sysDefs[DIV_SYSTEM_SNES]=new DivSysDef(
|
||||||
"SNES", NULL, 0x87, 0, 8, false, true, 0, false,
|
"SNES", NULL, 0x87, 0, 8, false, true, 0, false,
|
||||||
|
"FM? nah... samples! Nintendo's answer to Sega.",
|
||||||
{"Channel 1", "Channel 2", "Channel 3", "Channel 4", "Channel 5", "Channel 6", "Channel 7", "Channel 8"},
|
{"Channel 1", "Channel 2", "Channel 3", "Channel 4", "Channel 5", "Channel 6", "Channel 7", "Channel 8"},
|
||||||
{"CH1", "CH2", "CH3", "CH4", "CH5", "CH6", "CH7", "CH8"},
|
{"CH1", "CH2", "CH3", "CH4", "CH5", "CH6", "CH7", "CH8"},
|
||||||
{DIV_CH_PCM, DIV_CH_PCM, DIV_CH_PCM, DIV_CH_PCM, DIV_CH_PCM, DIV_CH_PCM, DIV_CH_PCM, DIV_CH_PCM},
|
{DIV_CH_PCM, DIV_CH_PCM, DIV_CH_PCM, DIV_CH_PCM, DIV_CH_PCM, DIV_CH_PCM, DIV_CH_PCM, DIV_CH_PCM},
|
||||||
|
|
@ -1105,6 +1130,7 @@ void DivEngine::registerSystems() {
|
||||||
|
|
||||||
sysDefs[DIV_SYSTEM_VRC6]=new DivSysDef(
|
sysDefs[DIV_SYSTEM_VRC6]=new DivSysDef(
|
||||||
"Konami VRC6", NULL, 0x88, 0, 3, false, true, 0, false,
|
"Konami VRC6", NULL, 0x88, 0, 3, false, true, 0, false,
|
||||||
|
"an expansion chip for the Famicom, featuring a quirky sawtooth channel.",
|
||||||
{"VRC6 1", "VRC6 2", "VRC6 Saw"},
|
{"VRC6 1", "VRC6 2", "VRC6 Saw"},
|
||||||
{"V1", "V2", "VS"},
|
{"V1", "V2", "VS"},
|
||||||
{DIV_CH_PULSE, DIV_CH_PULSE, DIV_CH_WAVE},
|
{DIV_CH_PULSE, DIV_CH_PULSE, DIV_CH_WAVE},
|
||||||
|
|
@ -1138,6 +1164,7 @@ void DivEngine::registerSystems() {
|
||||||
|
|
||||||
sysDefs[DIV_SYSTEM_OPLL]=new DivSysDef(
|
sysDefs[DIV_SYSTEM_OPLL]=new DivSysDef(
|
||||||
"Yamaha YM2413 (OPLL)", NULL, 0x89, 0, 9, true, false, 0x150, false,
|
"Yamaha YM2413 (OPLL)", NULL, 0x89, 0, 9, true, false, 0x150, false,
|
||||||
|
"cost-reduced version of the OPL with 16 patches and only one of them is user-configurable.",
|
||||||
{"FM 1", "FM 2", "FM 3", "FM 4", "FM 5", "FM 6", "FM 7", "FM 8", "FM 9"},
|
{"FM 1", "FM 2", "FM 3", "FM 4", "FM 5", "FM 6", "FM 7", "FM 8", "FM 9"},
|
||||||
{"F1", "F2", "F3", "F4", "F5", "F6", "F7", "F8", "F9"},
|
{"F1", "F2", "F3", "F4", "F5", "F6", "F7", "F8", "F9"},
|
||||||
{DIV_CH_FM, DIV_CH_FM, DIV_CH_FM, DIV_CH_FM, DIV_CH_FM, DIV_CH_FM, DIV_CH_FM, DIV_CH_FM, DIV_CH_FM},
|
{DIV_CH_FM, DIV_CH_FM, DIV_CH_FM, DIV_CH_FM, DIV_CH_FM, DIV_CH_FM, DIV_CH_FM, DIV_CH_FM, DIV_CH_FM},
|
||||||
|
|
@ -1149,6 +1176,7 @@ void DivEngine::registerSystems() {
|
||||||
|
|
||||||
sysDefs[DIV_SYSTEM_FDS]=new DivSysDef(
|
sysDefs[DIV_SYSTEM_FDS]=new DivSysDef(
|
||||||
"Famicom Disk System (chip)", NULL, 0x8a, 0, 1, false, true, 0x161, false,
|
"Famicom Disk System (chip)", NULL, 0x8a, 0, 1, false, true, 0x161, false,
|
||||||
|
"a disk drive for the Famicom which also contains one wavetable channel.",
|
||||||
{"FDS"},
|
{"FDS"},
|
||||||
{"FDS"},
|
{"FDS"},
|
||||||
{DIV_CH_WAVE},
|
{DIV_CH_WAVE},
|
||||||
|
|
@ -1183,6 +1211,7 @@ void DivEngine::registerSystems() {
|
||||||
|
|
||||||
sysDefs[DIV_SYSTEM_MMC5]=new DivSysDef(
|
sysDefs[DIV_SYSTEM_MMC5]=new DivSysDef(
|
||||||
"MMC5", NULL, 0x8b, 0, 3, false, true, 0, false,
|
"MMC5", NULL, 0x8b, 0, 3, false, true, 0, false,
|
||||||
|
"an expansion chip for the Famicom, featuring a little-known PCM channel.",
|
||||||
{"Pulse 1", "Pulse 2", "PCM"},
|
{"Pulse 1", "Pulse 2", "PCM"},
|
||||||
{"S1", "S2", "PCM"},
|
{"S1", "S2", "PCM"},
|
||||||
{DIV_CH_PULSE, DIV_CH_PULSE, DIV_CH_PCM},
|
{DIV_CH_PULSE, DIV_CH_PULSE, DIV_CH_PCM},
|
||||||
|
|
@ -1205,6 +1234,7 @@ void DivEngine::registerSystems() {
|
||||||
|
|
||||||
sysDefs[DIV_SYSTEM_N163]=new DivSysDef(
|
sysDefs[DIV_SYSTEM_N163]=new DivSysDef(
|
||||||
"Namco 163", NULL, 0x8c, 0, 8, false, true, 0, false,
|
"Namco 163", NULL, 0x8c, 0, 8, false, true, 0, false,
|
||||||
|
"an expansion chip for the Famicom, with full wavetable.",
|
||||||
{"Channel 1", "Channel 2", "Channel 3", "Channel 4", "Channel 5", "Channel 6", "Channel 7", "Channel 8"},
|
{"Channel 1", "Channel 2", "Channel 3", "Channel 4", "Channel 5", "Channel 6", "Channel 7", "Channel 8"},
|
||||||
{"CH1", "CH2", "CH3", "CH4", "CH5", "CH6", "CH7", "CH8"},
|
{"CH1", "CH2", "CH3", "CH4", "CH5", "CH6", "CH7", "CH8"},
|
||||||
{DIV_CH_WAVE, DIV_CH_WAVE, DIV_CH_WAVE, DIV_CH_WAVE, DIV_CH_WAVE, DIV_CH_WAVE, DIV_CH_WAVE, DIV_CH_WAVE},
|
{DIV_CH_WAVE, DIV_CH_WAVE, DIV_CH_WAVE, DIV_CH_WAVE, DIV_CH_WAVE, DIV_CH_WAVE, DIV_CH_WAVE, DIV_CH_WAVE},
|
||||||
|
|
@ -1259,7 +1289,8 @@ void DivEngine::registerSystems() {
|
||||||
);
|
);
|
||||||
|
|
||||||
sysDefs[DIV_SYSTEM_OPN]=new DivSysDef(
|
sysDefs[DIV_SYSTEM_OPN]=new DivSysDef(
|
||||||
"Yamaha YM2203 (OPN)", NULL, 0x8d, 0, 6, true, false, 0x151, false,
|
"Yamaha YM2203 (OPN)", NULL, 0x8d, 0, 6, true, true, 0x151, false,
|
||||||
|
"cost-reduced version of the OPM with a different register layout and no stereo...\n...but it has a built-in AY-3-8910! (actually an YM2149)",
|
||||||
{"FM 1", "FM 2", "FM 3", "PSG 1", "PSG 2", "PSG 3"},
|
{"FM 1", "FM 2", "FM 3", "PSG 1", "PSG 2", "PSG 3"},
|
||||||
{"F1", "F2", "F3", "S1", "S2", "S3"},
|
{"F1", "F2", "F3", "S1", "S2", "S3"},
|
||||||
{DIV_CH_FM, DIV_CH_FM, DIV_CH_FM, DIV_CH_PULSE, DIV_CH_PULSE, DIV_CH_PULSE},
|
{DIV_CH_FM, DIV_CH_FM, DIV_CH_FM, DIV_CH_PULSE, DIV_CH_PULSE, DIV_CH_PULSE},
|
||||||
|
|
@ -1269,16 +1300,45 @@ void DivEngine::registerSystems() {
|
||||||
fmPostEffectHandler
|
fmPostEffectHandler
|
||||||
);
|
);
|
||||||
|
|
||||||
|
sysDefs[DIV_SYSTEM_OPN_EXT]=new DivSysDef(
|
||||||
|
"Yamaha YM2203 (OPN) Extended Channel 3", NULL, 0xb6, 0, 9, true, true, 0x151, false,
|
||||||
|
"cost-reduced version of the OPM with a different register layout and no stereo...\n...but it has a built-in AY-3-8910! (actually an YM2149)\nthis one is in Extended Channel mode, which turns the second FM channel into four operators with independent notes/frequencies",
|
||||||
|
{"FM 1", "FM 2", "FM 3 OP1", "FM 3 OP2", "FM 3 OP3", "FM 3 OP4", "PSG 1", "PSG 2", "PSG 3"},
|
||||||
|
{"F1", "F2", "O1", "O2", "O3", "O4", "S1", "S2", "S3"},
|
||||||
|
{DIV_CH_FM, DIV_CH_FM, DIV_CH_OP, DIV_CH_OP, DIV_CH_OP, DIV_CH_OP, DIV_CH_PULSE, DIV_CH_PULSE, DIV_CH_PULSE},
|
||||||
|
{DIV_INS_FM, DIV_INS_FM, DIV_INS_FM, DIV_INS_FM, DIV_INS_FM, DIV_INS_FM, DIV_INS_AY, DIV_INS_AY, DIV_INS_AY},
|
||||||
|
{},
|
||||||
|
fmHardResetEffectHandler,
|
||||||
|
fmPostEffectHandler
|
||||||
|
);
|
||||||
|
|
||||||
sysDefs[DIV_SYSTEM_PC98]=new DivSysDef(
|
sysDefs[DIV_SYSTEM_PC98]=new DivSysDef(
|
||||||
"Yamaha YM2608 (OPNA)", NULL, 0x8e, 0, 16, true, false, 0, false,
|
"Yamaha YM2608 (OPNA)", NULL, 0x8e, 0, 16, true, true, 0, false,
|
||||||
|
"OPN but twice the FM channels, stereo makes a come-back and has rhythm and ADPCM channels.",
|
||||||
{"FM 1", "FM 2", "FM 3", "FM 4", "FM 5", "FM 6", "Square 1", "Square 2", "Square 3", "Kick", "Snare", "Top", "HiHat", "Tom", "Rim", "ADPCM"},
|
{"FM 1", "FM 2", "FM 3", "FM 4", "FM 5", "FM 6", "Square 1", "Square 2", "Square 3", "Kick", "Snare", "Top", "HiHat", "Tom", "Rim", "ADPCM"},
|
||||||
{"F1", "F2", "F3", "F4", "F5", "F6", "S1", "S2", "S3", "BD", "SD", "TP", "HH", "TM", "RM", "P"},
|
{"F1", "F2", "F3", "F4", "F5", "F6", "S1", "S2", "S3", "BD", "SD", "TP", "HH", "TM", "RM", "P"},
|
||||||
{DIV_CH_FM, DIV_CH_FM, DIV_CH_FM, DIV_CH_FM, DIV_CH_FM, DIV_CH_FM, DIV_CH_PULSE, DIV_CH_PULSE, DIV_CH_PULSE, DIV_CH_NOISE, DIV_CH_NOISE, DIV_CH_NOISE, DIV_CH_NOISE, DIV_CH_NOISE, DIV_CH_NOISE, DIV_CH_PCM},
|
{DIV_CH_FM, DIV_CH_FM, DIV_CH_FM, DIV_CH_FM, DIV_CH_FM, DIV_CH_FM, DIV_CH_PULSE, DIV_CH_PULSE, DIV_CH_PULSE, DIV_CH_NOISE, DIV_CH_NOISE, DIV_CH_NOISE, DIV_CH_NOISE, DIV_CH_NOISE, DIV_CH_NOISE, DIV_CH_PCM},
|
||||||
{DIV_INS_FM, DIV_INS_FM, DIV_INS_FM, DIV_INS_FM, DIV_INS_FM, DIV_INS_FM, DIV_INS_AY, DIV_INS_AY, DIV_INS_AY, DIV_INS_AMIGA, DIV_INS_AMIGA, DIV_INS_AMIGA, DIV_INS_AMIGA, DIV_INS_AMIGA, DIV_INS_AMIGA, DIV_INS_AMIGA}
|
{DIV_INS_FM, DIV_INS_FM, DIV_INS_FM, DIV_INS_FM, DIV_INS_FM, DIV_INS_FM, DIV_INS_AY, DIV_INS_AY, DIV_INS_AY, DIV_INS_NULL, DIV_INS_NULL, DIV_INS_NULL, DIV_INS_NULL, DIV_INS_NULL, DIV_INS_NULL, DIV_INS_AMIGA},
|
||||||
|
{},
|
||||||
|
fmHardResetEffectHandler,
|
||||||
|
fmPostEffectHandler
|
||||||
|
);
|
||||||
|
|
||||||
|
sysDefs[DIV_SYSTEM_PC98_EXT]=new DivSysDef(
|
||||||
|
"Yamaha YM2608 (OPNA) Extended Channel 3", NULL, 0xb7, 0, 19, true, true, 0, false,
|
||||||
|
"OPN but twice the FM channels, stereo makes a come-back and has rhythm and ADPCM channels.\nthis one is in Extended Channel mode, which turns the second FM channel into four operators with independent notes/frequencies",
|
||||||
|
{"FM 1", "FM 2", "FM 3 OP1", "FM 3 OP2", "FM 3 OP3", "FM 3 OP4", "FM 4", "FM 5", "FM 6", "Square 1", "Square 2", "Square 3", "Kick", "Snare", "Top", "HiHat", "Tom", "Rim", "ADPCM"},
|
||||||
|
{"F1", "F2", "O1", "O2", "O3", "O4", "F4", "F5", "F6", "S1", "S2", "S3", "BD", "SD", "TP", "HH", "TM", "RM", "P"},
|
||||||
|
{DIV_CH_FM, DIV_CH_FM, DIV_CH_OP, DIV_CH_OP, DIV_CH_OP, DIV_CH_OP, DIV_CH_FM, DIV_CH_FM, DIV_CH_FM, DIV_CH_PULSE, DIV_CH_PULSE, DIV_CH_PULSE, DIV_CH_NOISE, DIV_CH_NOISE, DIV_CH_NOISE, DIV_CH_NOISE, DIV_CH_NOISE, DIV_CH_NOISE, DIV_CH_PCM},
|
||||||
|
{DIV_INS_FM, DIV_INS_FM, DIV_INS_FM, DIV_INS_FM, DIV_INS_FM, DIV_INS_FM, DIV_INS_FM, DIV_INS_FM, DIV_INS_FM, DIV_INS_AY, DIV_INS_AY, DIV_INS_AY, DIV_INS_NULL, DIV_INS_NULL, DIV_INS_NULL, DIV_INS_NULL, DIV_INS_NULL, DIV_INS_NULL, DIV_INS_AMIGA},
|
||||||
|
{},
|
||||||
|
fmHardResetEffectHandler,
|
||||||
|
fmPostEffectHandler
|
||||||
);
|
);
|
||||||
|
|
||||||
sysDefs[DIV_SYSTEM_OPL]=new DivSysDef(
|
sysDefs[DIV_SYSTEM_OPL]=new DivSysDef(
|
||||||
"Yamaha YM3526 (OPL)", NULL, 0x8f, 0, 9, true, false, 0x151, false,
|
"Yamaha YM3526 (OPL)", NULL, 0x8f, 0, 9, true, false, 0x151, false,
|
||||||
|
"OPN, but what if you only had two operators, no stereo, no detune and a lower ADSR parameter range?",
|
||||||
{"FM 1", "FM 2", "FM 3", "FM 4", "FM 5", "FM 6", "FM 7", "FM 8", "FM 9"},
|
{"FM 1", "FM 2", "FM 3", "FM 4", "FM 5", "FM 6", "FM 7", "FM 8", "FM 9"},
|
||||||
{"F1", "F2", "F3", "F4", "F5", "F6", "F7", "F8", "F9"},
|
{"F1", "F2", "F3", "F4", "F5", "F6", "F7", "F8", "F9"},
|
||||||
{DIV_CH_FM, DIV_CH_FM, DIV_CH_FM, DIV_CH_FM, DIV_CH_FM, DIV_CH_FM, DIV_CH_FM, DIV_CH_FM, DIV_CH_FM},
|
{DIV_CH_FM, DIV_CH_FM, DIV_CH_FM, DIV_CH_FM, DIV_CH_FM, DIV_CH_FM, DIV_CH_FM, DIV_CH_FM, DIV_CH_FM},
|
||||||
|
|
@ -1290,6 +1350,7 @@ void DivEngine::registerSystems() {
|
||||||
|
|
||||||
sysDefs[DIV_SYSTEM_OPL2]=new DivSysDef(
|
sysDefs[DIV_SYSTEM_OPL2]=new DivSysDef(
|
||||||
"Yamaha YM3812 (OPL2)", NULL, 0x90, 0, 9, true, false, 0x151, false,
|
"Yamaha YM3812 (OPL2)", NULL, 0x90, 0, 9, true, false, 0x151, false,
|
||||||
|
"OPL, but what if you had more waveforms to choose than the normal sine?",
|
||||||
{"FM 1", "FM 2", "FM 3", "FM 4", "FM 5", "FM 6", "FM 7", "FM 8", "FM 9"},
|
{"FM 1", "FM 2", "FM 3", "FM 4", "FM 5", "FM 6", "FM 7", "FM 8", "FM 9"},
|
||||||
{"F1", "F2", "F3", "F4", "F5", "F6", "F7", "F8", "F9"},
|
{"F1", "F2", "F3", "F4", "F5", "F6", "F7", "F8", "F9"},
|
||||||
{DIV_CH_FM, DIV_CH_FM, DIV_CH_FM, DIV_CH_FM, DIV_CH_FM, DIV_CH_FM, DIV_CH_FM, DIV_CH_FM, DIV_CH_FM},
|
{DIV_CH_FM, DIV_CH_FM, DIV_CH_FM, DIV_CH_FM, DIV_CH_FM, DIV_CH_FM, DIV_CH_FM, DIV_CH_FM, DIV_CH_FM},
|
||||||
|
|
@ -1301,6 +1362,7 @@ void DivEngine::registerSystems() {
|
||||||
|
|
||||||
sysDefs[DIV_SYSTEM_OPL3]=new DivSysDef(
|
sysDefs[DIV_SYSTEM_OPL3]=new DivSysDef(
|
||||||
"Yamaha YMF262 (OPL3)", NULL, 0x91, 0, 18, true, false, 0x151, false,
|
"Yamaha YMF262 (OPL3)", NULL, 0x91, 0, 18, true, false, 0x151, false,
|
||||||
|
"OPL2, but what if you had twice the channels, 4-op mode, stereo and even more waveforms?",
|
||||||
{"4OP 1", "FM 2", "4OP 3", "FM 4", "4OP 5", "FM 6", "4OP 7", "FM 8", "4OP 9", "FM 10", "4OP 11", "FM 12", "FM 13", "FM 14", "FM 15", "FM 16", "FM 17", "FM 18"},
|
{"4OP 1", "FM 2", "4OP 3", "FM 4", "4OP 5", "FM 6", "4OP 7", "FM 8", "4OP 9", "FM 10", "4OP 11", "FM 12", "FM 13", "FM 14", "FM 15", "FM 16", "FM 17", "FM 18"},
|
||||||
{"1", "2", "3", "4", "5", "6", "7", "8", "9", "10", "11", "12", "13", "14", "15", "16", "17", "18"},
|
{"1", "2", "3", "4", "5", "6", "7", "8", "9", "10", "11", "12", "13", "14", "15", "16", "17", "18"},
|
||||||
{DIV_CH_OP, DIV_CH_FM, DIV_CH_OP, DIV_CH_FM, DIV_CH_OP, DIV_CH_FM, DIV_CH_OP, DIV_CH_FM, DIV_CH_OP, DIV_CH_FM, DIV_CH_OP, DIV_CH_FM, DIV_CH_FM, DIV_CH_FM, DIV_CH_FM, DIV_CH_FM, DIV_CH_FM, DIV_CH_FM},
|
{DIV_CH_OP, DIV_CH_FM, DIV_CH_OP, DIV_CH_FM, DIV_CH_OP, DIV_CH_FM, DIV_CH_OP, DIV_CH_FM, DIV_CH_OP, DIV_CH_FM, DIV_CH_OP, DIV_CH_FM, DIV_CH_FM, DIV_CH_FM, DIV_CH_FM, DIV_CH_FM, DIV_CH_FM, DIV_CH_FM},
|
||||||
|
|
@ -1312,6 +1374,7 @@ void DivEngine::registerSystems() {
|
||||||
|
|
||||||
sysDefs[DIV_SYSTEM_MULTIPCM]=new DivSysDef(
|
sysDefs[DIV_SYSTEM_MULTIPCM]=new DivSysDef(
|
||||||
"MultiPCM", NULL, 0x92, 0, 28, false, true, 0, false,
|
"MultiPCM", NULL, 0x92, 0, 28, false, true, 0, false,
|
||||||
|
"how many channels of PCM do you want?\nMultiPCM: yes",
|
||||||
{"Channel 1", "Channel 2", "Channel 3", "Channel 4", "Channel 5", "Channel 6", "Channel 7", "Channel 8", "Channel 9", "Channel 10", "Channel 11", "Channel 12", "Channel 13", "Channel 14", "Channel 15", "Channel 16", "Channel 17", "Channel 18", "Channel 19", "Channel 20", "Channel 21", "Channel 22", "Channel 23", "Channel 24", "Channel 25", "Channel 26", "Channel 27", "Channel 28"},
|
{"Channel 1", "Channel 2", "Channel 3", "Channel 4", "Channel 5", "Channel 6", "Channel 7", "Channel 8", "Channel 9", "Channel 10", "Channel 11", "Channel 12", "Channel 13", "Channel 14", "Channel 15", "Channel 16", "Channel 17", "Channel 18", "Channel 19", "Channel 20", "Channel 21", "Channel 22", "Channel 23", "Channel 24", "Channel 25", "Channel 26", "Channel 27", "Channel 28"},
|
||||||
{"1", "2", "3", "4", "5", "6", "7", "8", "9", "10", "11", "12", "13", "14", "15", "16", "17", "18", "19", "20", "21", "22", "23", "24", "25", "26", "27", "28"},
|
{"1", "2", "3", "4", "5", "6", "7", "8", "9", "10", "11", "12", "13", "14", "15", "16", "17", "18", "19", "20", "21", "22", "23", "24", "25", "26", "27", "28"},
|
||||||
{DIV_CH_PCM, DIV_CH_PCM, DIV_CH_PCM, DIV_CH_PCM, DIV_CH_PCM, DIV_CH_PCM, DIV_CH_PCM, DIV_CH_PCM, DIV_CH_PCM, DIV_CH_PCM, DIV_CH_PCM, DIV_CH_PCM, DIV_CH_PCM, DIV_CH_PCM, DIV_CH_PCM, DIV_CH_PCM, DIV_CH_PCM, DIV_CH_PCM, DIV_CH_PCM, DIV_CH_PCM, DIV_CH_PCM, DIV_CH_PCM, DIV_CH_PCM, DIV_CH_PCM, DIV_CH_PCM, DIV_CH_PCM, DIV_CH_PCM, DIV_CH_PCM},
|
{DIV_CH_PCM, DIV_CH_PCM, DIV_CH_PCM, DIV_CH_PCM, DIV_CH_PCM, DIV_CH_PCM, DIV_CH_PCM, DIV_CH_PCM, DIV_CH_PCM, DIV_CH_PCM, DIV_CH_PCM, DIV_CH_PCM, DIV_CH_PCM, DIV_CH_PCM, DIV_CH_PCM, DIV_CH_PCM, DIV_CH_PCM, DIV_CH_PCM, DIV_CH_PCM, DIV_CH_PCM, DIV_CH_PCM, DIV_CH_PCM, DIV_CH_PCM, DIV_CH_PCM, DIV_CH_PCM, DIV_CH_PCM, DIV_CH_PCM, DIV_CH_PCM},
|
||||||
|
|
@ -1320,14 +1383,16 @@ void DivEngine::registerSystems() {
|
||||||
|
|
||||||
sysDefs[DIV_SYSTEM_PCSPKR]=new DivSysDef(
|
sysDefs[DIV_SYSTEM_PCSPKR]=new DivSysDef(
|
||||||
"PC Speaker", NULL, 0x93, 0, 1, false, true, 0, false,
|
"PC Speaker", NULL, 0x93, 0, 1, false, true, 0, false,
|
||||||
|
"good luck!",
|
||||||
{"Square"},
|
{"Square"},
|
||||||
{"SQ"},
|
{"SQ"},
|
||||||
{DIV_CH_PULSE},
|
{DIV_CH_PULSE},
|
||||||
{DIV_INS_STD}
|
{DIV_INS_BEEPER}
|
||||||
);
|
);
|
||||||
|
|
||||||
sysDefs[DIV_SYSTEM_POKEY]=new DivSysDef(
|
sysDefs[DIV_SYSTEM_POKEY]=new DivSysDef(
|
||||||
"POKEY", NULL, 0x94, 0, 4, false, true, 0, false,
|
"POKEY", NULL, 0x94, 0, 4, false, true, 0, false,
|
||||||
|
"TIA, but better and more flexible.\nused in the Atari 8-bit family of computers (400/800/XL/XE).",
|
||||||
{"Channel 1", "Channel 2", "Channel 3", "Channel 4"},
|
{"Channel 1", "Channel 2", "Channel 3", "Channel 4"},
|
||||||
{"CH1", "CH2", "CH3", "CH4"},
|
{"CH1", "CH2", "CH3", "CH4"},
|
||||||
{DIV_CH_WAVE, DIV_CH_WAVE, DIV_CH_WAVE, DIV_CH_WAVE},
|
{DIV_CH_WAVE, DIV_CH_WAVE, DIV_CH_WAVE, DIV_CH_WAVE},
|
||||||
|
|
@ -1336,6 +1401,7 @@ void DivEngine::registerSystems() {
|
||||||
|
|
||||||
sysDefs[DIV_SYSTEM_RF5C68]=new DivSysDef(
|
sysDefs[DIV_SYSTEM_RF5C68]=new DivSysDef(
|
||||||
"Ricoh RF5C68", NULL, 0x95, 0, 8, false, true, 0, false,
|
"Ricoh RF5C68", NULL, 0x95, 0, 8, false, true, 0, false,
|
||||||
|
"this is like SNES' sound chip but without interpolation and the rest of nice bits.",
|
||||||
{"Channel 1", "Channel 2", "Channel 3", "Channel 4", "Channel 5", "Channel 6", "Channel 7", "Channel 8"},
|
{"Channel 1", "Channel 2", "Channel 3", "Channel 4", "Channel 5", "Channel 6", "Channel 7", "Channel 8"},
|
||||||
{"CH1", "CH2", "CH3", "CH4", "CH5", "CH6", "CH7", "CH8"},
|
{"CH1", "CH2", "CH3", "CH4", "CH5", "CH6", "CH7", "CH8"},
|
||||||
{DIV_CH_PCM, DIV_CH_PCM, DIV_CH_PCM, DIV_CH_PCM, DIV_CH_PCM, DIV_CH_PCM, DIV_CH_PCM, DIV_CH_PCM},
|
{DIV_CH_PCM, DIV_CH_PCM, DIV_CH_PCM, DIV_CH_PCM, DIV_CH_PCM, DIV_CH_PCM, DIV_CH_PCM, DIV_CH_PCM},
|
||||||
|
|
@ -1344,6 +1410,7 @@ void DivEngine::registerSystems() {
|
||||||
|
|
||||||
sysDefs[DIV_SYSTEM_SWAN]=new DivSysDef(
|
sysDefs[DIV_SYSTEM_SWAN]=new DivSysDef(
|
||||||
"WonderSwan", NULL, 0x96, 0, 4, false, true, 0x171, false,
|
"WonderSwan", NULL, 0x96, 0, 4, false, true, 0x171, false,
|
||||||
|
"developed by the same team under the Game Boy and the Virtual Boy...",
|
||||||
{"Wave", "Wave/PCM", "Wave", "Wave/Noise"},
|
{"Wave", "Wave/PCM", "Wave", "Wave/Noise"},
|
||||||
{"CH1", "CH2", "CH3", "CH4"},
|
{"CH1", "CH2", "CH3", "CH4"},
|
||||||
{DIV_CH_WAVE, DIV_CH_PCM, DIV_CH_WAVE, DIV_CH_NOISE},
|
{DIV_CH_WAVE, DIV_CH_PCM, DIV_CH_WAVE, DIV_CH_NOISE},
|
||||||
|
|
@ -1375,6 +1442,7 @@ void DivEngine::registerSystems() {
|
||||||
|
|
||||||
sysDefs[DIV_SYSTEM_OPZ]=new DivSysDef(
|
sysDefs[DIV_SYSTEM_OPZ]=new DivSysDef(
|
||||||
"Yamaha YM2414 (OPZ)", NULL, 0x98, 0, 8, true, false, 0, false,
|
"Yamaha YM2414 (OPZ)", NULL, 0x98, 0, 8, true, false, 0, false,
|
||||||
|
"like OPM, but with more waveforms, fixed frequency mode and totally... undocumented.\nused in the Yamaha TX81Z and some other synthesizers.",
|
||||||
{"FM 1", "FM 2", "FM 3", "FM 4", "FM 5", "FM 6", "FM 7", "FM 8"},
|
{"FM 1", "FM 2", "FM 3", "FM 4", "FM 5", "FM 6", "FM 7", "FM 8"},
|
||||||
{"F1", "F2", "F3", "F4", "F5", "F6", "F7", "F8"},
|
{"F1", "F2", "F3", "F4", "F5", "F6", "F7", "F8"},
|
||||||
{DIV_CH_FM, DIV_CH_FM, DIV_CH_FM, DIV_CH_FM, DIV_CH_FM, DIV_CH_FM, DIV_CH_FM, DIV_CH_FM},
|
{DIV_CH_FM, DIV_CH_FM, DIV_CH_FM, DIV_CH_FM, DIV_CH_FM, DIV_CH_FM, DIV_CH_FM, DIV_CH_FM},
|
||||||
|
|
@ -1395,6 +1463,7 @@ void DivEngine::registerSystems() {
|
||||||
|
|
||||||
sysDefs[DIV_SYSTEM_POKEMINI]=new DivSysDef(
|
sysDefs[DIV_SYSTEM_POKEMINI]=new DivSysDef(
|
||||||
"Pokémon Mini", NULL, 0x99, 0, 1, false, true, 0, false,
|
"Pokémon Mini", NULL, 0x99, 0, 1, false, true, 0, false,
|
||||||
|
"this one is like PC Speaker but has duty cycles.",
|
||||||
{"Square"},
|
{"Square"},
|
||||||
{"SQ"},
|
{"SQ"},
|
||||||
{DIV_CH_PULSE},
|
{DIV_CH_PULSE},
|
||||||
|
|
@ -1403,6 +1472,7 @@ void DivEngine::registerSystems() {
|
||||||
|
|
||||||
sysDefs[DIV_SYSTEM_SEGAPCM]=new DivSysDef(
|
sysDefs[DIV_SYSTEM_SEGAPCM]=new DivSysDef(
|
||||||
"SegaPCM", NULL, 0x9b, 0, 16, false, true, 0x151, false,
|
"SegaPCM", NULL, 0x9b, 0, 16, false, true, 0x151, false,
|
||||||
|
"used in some Sega arcade boards (like OutRun), and usually paired with a YM2151.",
|
||||||
{"Channel 1", "Channel 2", "Channel 3", "Channel 4", "Channel 5", "Channel 6", "Channel 7", "Channel 8", "Channel 9", "Channel 10", "Channel 11", "Channel 12", "Channel 13", "Channel 14", "Channel 15", "Channel 16"},
|
{"Channel 1", "Channel 2", "Channel 3", "Channel 4", "Channel 5", "Channel 6", "Channel 7", "Channel 8", "Channel 9", "Channel 10", "Channel 11", "Channel 12", "Channel 13", "Channel 14", "Channel 15", "Channel 16"},
|
||||||
{"1", "2", "3", "4", "5", "6", "7", "8", "9", "10", "11", "12", "13", "14", "15", "16"},
|
{"1", "2", "3", "4", "5", "6", "7", "8", "9", "10", "11", "12", "13", "14", "15", "16"},
|
||||||
{DIV_CH_PCM, DIV_CH_PCM, DIV_CH_PCM, DIV_CH_PCM, DIV_CH_PCM, DIV_CH_PCM, DIV_CH_PCM, DIV_CH_PCM, DIV_CH_PCM, DIV_CH_PCM, DIV_CH_PCM, DIV_CH_PCM, DIV_CH_PCM, DIV_CH_PCM, DIV_CH_PCM, DIV_CH_PCM},
|
{DIV_CH_PCM, DIV_CH_PCM, DIV_CH_PCM, DIV_CH_PCM, DIV_CH_PCM, DIV_CH_PCM, DIV_CH_PCM, DIV_CH_PCM, DIV_CH_PCM, DIV_CH_PCM, DIV_CH_PCM, DIV_CH_PCM, DIV_CH_PCM, DIV_CH_PCM, DIV_CH_PCM, DIV_CH_PCM},
|
||||||
|
|
@ -1414,6 +1484,7 @@ void DivEngine::registerSystems() {
|
||||||
|
|
||||||
sysDefs[DIV_SYSTEM_VBOY]=new DivSysDef(
|
sysDefs[DIV_SYSTEM_VBOY]=new DivSysDef(
|
||||||
"Virtual Boy", NULL, 0x9c, 0, 6, false, true, 0, false,
|
"Virtual Boy", NULL, 0x9c, 0, 6, false, true, 0, false,
|
||||||
|
"a console which failed to sell well due to its headache-inducing features.",
|
||||||
{"Channel 1", "Channel 2", "Channel 3", "Channel 4", "Channel 5", "Noise"},
|
{"Channel 1", "Channel 2", "Channel 3", "Channel 4", "Channel 5", "Noise"},
|
||||||
{"CH1", "CH2", "CH3", "CH4", "CH5", "NO"},
|
{"CH1", "CH2", "CH3", "CH4", "CH5", "NO"},
|
||||||
{DIV_CH_WAVE, DIV_CH_WAVE, DIV_CH_WAVE, DIV_CH_WAVE, DIV_CH_WAVE, DIV_CH_NOISE},
|
{DIV_CH_WAVE, DIV_CH_WAVE, DIV_CH_WAVE, DIV_CH_WAVE, DIV_CH_WAVE, DIV_CH_NOISE},
|
||||||
|
|
@ -1422,6 +1493,7 @@ void DivEngine::registerSystems() {
|
||||||
|
|
||||||
sysDefs[DIV_SYSTEM_VRC7]=new DivSysDef(
|
sysDefs[DIV_SYSTEM_VRC7]=new DivSysDef(
|
||||||
"Konami VRC7", NULL, 0x9d, 0, 6, true, false, 0x151, false,
|
"Konami VRC7", NULL, 0x9d, 0, 6, true, false, 0x151, false,
|
||||||
|
"like OPLL, but even more cost reductions applied. three less FM channels, and no drums mode...",
|
||||||
{"FM 1", "FM 2", "FM 3", "FM 4", "FM 5", "FM 6"},
|
{"FM 1", "FM 2", "FM 3", "FM 4", "FM 5", "FM 6"},
|
||||||
{"F1", "F2", "F3", "F4", "F5", "F6"},
|
{"F1", "F2", "F3", "F4", "F5", "F6"},
|
||||||
{DIV_CH_FM, DIV_CH_FM, DIV_CH_FM, DIV_CH_FM, DIV_CH_FM, DIV_CH_FM},
|
{DIV_CH_FM, DIV_CH_FM, DIV_CH_FM, DIV_CH_FM, DIV_CH_FM, DIV_CH_FM},
|
||||||
|
|
@ -1433,6 +1505,7 @@ void DivEngine::registerSystems() {
|
||||||
|
|
||||||
sysDefs[DIV_SYSTEM_YM2610B]=new DivSysDef(
|
sysDefs[DIV_SYSTEM_YM2610B]=new DivSysDef(
|
||||||
"Yamaha YM2610B (OPNB-B)", NULL, 0x9e, 0, 16, true, false, 0x151, false,
|
"Yamaha YM2610B (OPNB-B)", NULL, 0x9e, 0, 16, true, false, 0x151, false,
|
||||||
|
"so Taito asked Yamaha if they could get the two missing FM channels back, and Yamaha gladly provided them with this chip.",
|
||||||
{"FM 1", "FM 2", "FM 3", "FM 4", "FM 5", "FM 6", "PSG 1", "PSG 2", "PSG 3", "ADPCM-A 1", "ADPCM-A 2", "ADPCM-A 3", "ADPCM-A 4", "ADPCM-A 5", "ADPCM-A 6", "ADPCM-B"},
|
{"FM 1", "FM 2", "FM 3", "FM 4", "FM 5", "FM 6", "PSG 1", "PSG 2", "PSG 3", "ADPCM-A 1", "ADPCM-A 2", "ADPCM-A 3", "ADPCM-A 4", "ADPCM-A 5", "ADPCM-A 6", "ADPCM-B"},
|
||||||
{"F1", "F2", "F3", "F4", "F5", "F6", "S1", "S2", "S3", "P1", "P2", "P3", "P4", "P5", "P6", "B"},
|
{"F1", "F2", "F3", "F4", "F5", "F6", "S1", "S2", "S3", "P1", "P2", "P3", "P4", "P5", "P6", "B"},
|
||||||
{DIV_CH_FM, DIV_CH_FM, DIV_CH_FM, DIV_CH_FM, DIV_CH_FM, DIV_CH_FM, DIV_CH_PULSE, DIV_CH_PULSE, DIV_CH_PULSE, DIV_CH_PCM, DIV_CH_PCM, DIV_CH_PCM, DIV_CH_PCM, DIV_CH_PCM, DIV_CH_PCM, DIV_CH_PCM},
|
{DIV_CH_FM, DIV_CH_FM, DIV_CH_FM, DIV_CH_FM, DIV_CH_FM, DIV_CH_FM, DIV_CH_PULSE, DIV_CH_PULSE, DIV_CH_PULSE, DIV_CH_PCM, DIV_CH_PCM, DIV_CH_PCM, DIV_CH_PCM, DIV_CH_PCM, DIV_CH_PCM, DIV_CH_PCM},
|
||||||
|
|
@ -1444,6 +1517,7 @@ void DivEngine::registerSystems() {
|
||||||
|
|
||||||
sysDefs[DIV_SYSTEM_SFX_BEEPER]=new DivSysDef(
|
sysDefs[DIV_SYSTEM_SFX_BEEPER]=new DivSysDef(
|
||||||
"ZX Spectrum Beeper", NULL, 0x9f, 0, 6, false, true, 0, false,
|
"ZX Spectrum Beeper", NULL, 0x9f, 0, 6, false, true, 0, false,
|
||||||
|
"the ZX Spectrum only had a basic beeper capable of...\n...a bunch of thin pulses and tons of other interesting stuff!\nFurnace provides a thin pulse system.",
|
||||||
{"Channel 1", "Channel 2", "Channel 3", "Channel 4", "Channel 5", "Channel 6"},
|
{"Channel 1", "Channel 2", "Channel 3", "Channel 4", "Channel 5", "Channel 6"},
|
||||||
{"CH1", "CH2", "CH3", "CH4", "CH5", "CH6"},
|
{"CH1", "CH2", "CH3", "CH4", "CH5", "CH6"},
|
||||||
{DIV_CH_WAVE, DIV_CH_WAVE, DIV_CH_WAVE, DIV_CH_WAVE, DIV_CH_WAVE, DIV_CH_WAVE},
|
{DIV_CH_WAVE, DIV_CH_WAVE, DIV_CH_WAVE, DIV_CH_WAVE, DIV_CH_WAVE, DIV_CH_WAVE},
|
||||||
|
|
@ -1452,6 +1526,7 @@ void DivEngine::registerSystems() {
|
||||||
|
|
||||||
sysDefs[DIV_SYSTEM_YM2612_EXT]=new DivSysDef(
|
sysDefs[DIV_SYSTEM_YM2612_EXT]=new DivSysDef(
|
||||||
"Yamaha YM2612 (OPN2) Extended Channel 3", NULL, 0xa0, 0, 9, true, false, 0x150, false,
|
"Yamaha YM2612 (OPN2) Extended Channel 3", NULL, 0xa0, 0, 9, true, false, 0x150, false,
|
||||||
|
"this chip is mostly known for being in the Sega Genesis (but it also was on the FM Towns computer).\nthis one is in Extended Channel mode, which turns the second FM channel into four operators with independent notes/frequencies.",
|
||||||
{"FM 1", "FM 2", "FM 3 OP1", "FM 3 OP2", "FM 3 OP3", "FM 3 OP4", "FM 4", "FM 5", "FM 6"},
|
{"FM 1", "FM 2", "FM 3 OP1", "FM 3 OP2", "FM 3 OP3", "FM 3 OP4", "FM 4", "FM 5", "FM 6"},
|
||||||
{"F1", "F2", "O1", "O2", "O3", "O4", "F4", "F5", "F6"},
|
{"F1", "F2", "O1", "O2", "O3", "O4", "F4", "F5", "F6"},
|
||||||
{DIV_CH_FM, DIV_CH_FM, DIV_CH_OP, DIV_CH_OP, DIV_CH_OP, DIV_CH_OP, DIV_CH_FM, DIV_CH_FM, DIV_CH_FM},
|
{DIV_CH_FM, DIV_CH_FM, DIV_CH_OP, DIV_CH_OP, DIV_CH_OP, DIV_CH_OP, DIV_CH_FM, DIV_CH_FM, DIV_CH_FM},
|
||||||
|
|
@ -1463,6 +1538,7 @@ void DivEngine::registerSystems() {
|
||||||
|
|
||||||
sysDefs[DIV_SYSTEM_SCC]=new DivSysDef(
|
sysDefs[DIV_SYSTEM_SCC]=new DivSysDef(
|
||||||
"Konami SCC", NULL, 0xa1, 0, 5, false, true, 0x161, false,
|
"Konami SCC", NULL, 0xa1, 0, 5, false, true, 0x161, false,
|
||||||
|
"a wavetable chip made by Konami for use with the MSX.\nthe last channel shares its wavetable with the previous one though.",
|
||||||
{"Channel 1", "Channel 2", "Channel 3", "Channel 4", "Channel 5"},
|
{"Channel 1", "Channel 2", "Channel 3", "Channel 4", "Channel 5"},
|
||||||
{"CH1", "CH2", "CH3", "CH4", "CH5"},
|
{"CH1", "CH2", "CH3", "CH4", "CH5"},
|
||||||
{DIV_CH_WAVE, DIV_CH_WAVE, DIV_CH_WAVE, DIV_CH_WAVE, DIV_CH_WAVE},
|
{DIV_CH_WAVE, DIV_CH_WAVE, DIV_CH_WAVE, DIV_CH_WAVE, DIV_CH_WAVE},
|
||||||
|
|
@ -1487,6 +1563,7 @@ void DivEngine::registerSystems() {
|
||||||
|
|
||||||
sysDefs[DIV_SYSTEM_OPL_DRUMS]=new DivSysDef(
|
sysDefs[DIV_SYSTEM_OPL_DRUMS]=new DivSysDef(
|
||||||
"Yamaha YM3526 (OPL) with drums", NULL, 0xa2, 0, 11, true, false, 0x151, false,
|
"Yamaha YM3526 (OPL) with drums", NULL, 0xa2, 0, 11, true, false, 0x151, false,
|
||||||
|
"the OPL chip but with drums mode enabled.",
|
||||||
{"FM 1", "FM 2", "FM 3", "FM 4", "FM 5", "FM 6", "Kick", "Snare", "Tom", "Top", "HiHat"},
|
{"FM 1", "FM 2", "FM 3", "FM 4", "FM 5", "FM 6", "Kick", "Snare", "Tom", "Top", "HiHat"},
|
||||||
{"F1", "F2", "F3", "F4", "F5", "F6", "BD", "SD", "TM", "TP", "HH"},
|
{"F1", "F2", "F3", "F4", "F5", "F6", "BD", "SD", "TM", "TP", "HH"},
|
||||||
{DIV_CH_FM, DIV_CH_FM, DIV_CH_FM, DIV_CH_FM, DIV_CH_FM, DIV_CH_FM, DIV_CH_NOISE, DIV_CH_NOISE, DIV_CH_NOISE, DIV_CH_NOISE, DIV_CH_NOISE},
|
{DIV_CH_FM, DIV_CH_FM, DIV_CH_FM, DIV_CH_FM, DIV_CH_FM, DIV_CH_FM, DIV_CH_NOISE, DIV_CH_NOISE, DIV_CH_NOISE, DIV_CH_NOISE, DIV_CH_NOISE},
|
||||||
|
|
@ -1498,6 +1575,7 @@ void DivEngine::registerSystems() {
|
||||||
|
|
||||||
sysDefs[DIV_SYSTEM_OPL2_DRUMS]=new DivSysDef(
|
sysDefs[DIV_SYSTEM_OPL2_DRUMS]=new DivSysDef(
|
||||||
"Yamaha YM3812 (OPL2) with drums", NULL, 0xa3, 0, 11, true, false, 0x151, false,
|
"Yamaha YM3812 (OPL2) with drums", NULL, 0xa3, 0, 11, true, false, 0x151, false,
|
||||||
|
"the OPL2 chip but with drums mode enabled.",
|
||||||
{"FM 1", "FM 2", "FM 3", "FM 4", "FM 5", "FM 6", "Kick", "Snare", "Tom", "Top", "HiHat"},
|
{"FM 1", "FM 2", "FM 3", "FM 4", "FM 5", "FM 6", "Kick", "Snare", "Tom", "Top", "HiHat"},
|
||||||
{"F1", "F2", "F3", "F4", "F5", "F6", "BD", "SD", "TM", "TP", "HH"},
|
{"F1", "F2", "F3", "F4", "F5", "F6", "BD", "SD", "TM", "TP", "HH"},
|
||||||
{DIV_CH_FM, DIV_CH_FM, DIV_CH_FM, DIV_CH_FM, DIV_CH_FM, DIV_CH_FM, DIV_CH_NOISE, DIV_CH_NOISE, DIV_CH_NOISE, DIV_CH_NOISE, DIV_CH_NOISE},
|
{DIV_CH_FM, DIV_CH_FM, DIV_CH_FM, DIV_CH_FM, DIV_CH_FM, DIV_CH_FM, DIV_CH_NOISE, DIV_CH_NOISE, DIV_CH_NOISE, DIV_CH_NOISE, DIV_CH_NOISE},
|
||||||
|
|
@ -1509,6 +1587,7 @@ void DivEngine::registerSystems() {
|
||||||
|
|
||||||
sysDefs[DIV_SYSTEM_OPL3_DRUMS]=new DivSysDef(
|
sysDefs[DIV_SYSTEM_OPL3_DRUMS]=new DivSysDef(
|
||||||
"Yamaha YMF262 (OPL3) with drums", NULL, 0xa4, 0, 20, true, false, 0x151, false,
|
"Yamaha YMF262 (OPL3) with drums", NULL, 0xa4, 0, 20, true, false, 0x151, false,
|
||||||
|
"the OPL3 chip but with drums mode enabled.",
|
||||||
{"4OP 1", "FM 2", "4OP 3", "FM 4", "4OP 5", "FM 6", "4OP 7", "FM 8", "4OP 9", "FM 10", "4OP 11", "FM 12", "FM 13", "FM 14", "FM 15", "Kick", "Snare", "Tom", "Top", "HiHat"},
|
{"4OP 1", "FM 2", "4OP 3", "FM 4", "4OP 5", "FM 6", "4OP 7", "FM 8", "4OP 9", "FM 10", "4OP 11", "FM 12", "FM 13", "FM 14", "FM 15", "Kick", "Snare", "Tom", "Top", "HiHat"},
|
||||||
{"1", "2", "3", "4", "5", "6", "7", "8", "9", "10", "11", "12", "13", "14", "15", "BD", "SD", "TM", "TP", "HH"},
|
{"1", "2", "3", "4", "5", "6", "7", "8", "9", "10", "11", "12", "13", "14", "15", "BD", "SD", "TM", "TP", "HH"},
|
||||||
{DIV_CH_OP, DIV_CH_FM, DIV_CH_OP, DIV_CH_FM, DIV_CH_OP, DIV_CH_FM, DIV_CH_OP, DIV_CH_FM, DIV_CH_OP, DIV_CH_FM, DIV_CH_OP, DIV_CH_FM, DIV_CH_FM, DIV_CH_FM, DIV_CH_FM, DIV_CH_NOISE, DIV_CH_NOISE, DIV_CH_NOISE, DIV_CH_NOISE, DIV_CH_NOISE},
|
{DIV_CH_OP, DIV_CH_FM, DIV_CH_OP, DIV_CH_FM, DIV_CH_OP, DIV_CH_FM, DIV_CH_OP, DIV_CH_FM, DIV_CH_OP, DIV_CH_FM, DIV_CH_OP, DIV_CH_FM, DIV_CH_FM, DIV_CH_FM, DIV_CH_FM, DIV_CH_NOISE, DIV_CH_NOISE, DIV_CH_NOISE, DIV_CH_NOISE, DIV_CH_NOISE},
|
||||||
|
|
@ -1520,6 +1599,7 @@ void DivEngine::registerSystems() {
|
||||||
|
|
||||||
sysDefs[DIV_SYSTEM_YM2610_FULL]=new DivSysDef(
|
sysDefs[DIV_SYSTEM_YM2610_FULL]=new DivSysDef(
|
||||||
"Yamaha YM2610 (OPNB)", NULL, 0xa5, 0, 14, true, false, 0x151, false,
|
"Yamaha YM2610 (OPNB)", NULL, 0xa5, 0, 14, true, false, 0x151, false,
|
||||||
|
"this chip was used in SNK's Neo Geo arcade board and video game console.\nit's like OPNA but the rhythm channels are ADPCM channels and two FM channels went missing.",
|
||||||
{"FM 1", "FM 2", "FM 3", "FM 4", "PSG 1", "PSG 2", "PSG 3", "ADPCM-A 1", "ADPCM-A 2", "ADPCM-A 3", "ADPCM-A 4", "ADPCM-A 5", "ADPCM-A 6", "ADPCM-B"},
|
{"FM 1", "FM 2", "FM 3", "FM 4", "PSG 1", "PSG 2", "PSG 3", "ADPCM-A 1", "ADPCM-A 2", "ADPCM-A 3", "ADPCM-A 4", "ADPCM-A 5", "ADPCM-A 6", "ADPCM-B"},
|
||||||
{"F1", "F2", "F3", "F4", "S1", "S2", "S3", "P1", "P2", "P3", "P4", "P5", "P6", "B"},
|
{"F1", "F2", "F3", "F4", "S1", "S2", "S3", "P1", "P2", "P3", "P4", "P5", "P6", "B"},
|
||||||
{DIV_CH_FM, DIV_CH_FM, DIV_CH_FM, DIV_CH_FM, DIV_CH_PULSE, DIV_CH_PULSE, DIV_CH_PULSE, DIV_CH_PCM, DIV_CH_PCM, DIV_CH_PCM, DIV_CH_PCM, DIV_CH_PCM, DIV_CH_PCM, DIV_CH_PCM},
|
{DIV_CH_FM, DIV_CH_FM, DIV_CH_FM, DIV_CH_FM, DIV_CH_PULSE, DIV_CH_PULSE, DIV_CH_PULSE, DIV_CH_PCM, DIV_CH_PCM, DIV_CH_PCM, DIV_CH_PCM, DIV_CH_PCM, DIV_CH_PCM, DIV_CH_PCM},
|
||||||
|
|
@ -1531,6 +1611,7 @@ void DivEngine::registerSystems() {
|
||||||
|
|
||||||
sysDefs[DIV_SYSTEM_YM2610_FULL_EXT]=new DivSysDef(
|
sysDefs[DIV_SYSTEM_YM2610_FULL_EXT]=new DivSysDef(
|
||||||
"Yamaha YM2610 (OPNB) Extended Channel 2", NULL, 0xa6, 0, 17, true, false, 0x151, false,
|
"Yamaha YM2610 (OPNB) Extended Channel 2", NULL, 0xa6, 0, 17, true, false, 0x151, false,
|
||||||
|
"this chip was used in SNK's Neo Geo arcade board and video game console.\nit's like OPNA but the rhythm channels are ADPCM channels and two FM channels went missing.\nthis one is in Extended Channel mode, which turns the second FM channel into four operators with independent notes/frequencies.",
|
||||||
{"FM 1", "FM 2 OP1", "FM 2 OP2", "FM 2 OP3", "FM 2 OP4", "FM 3", "FM 4", "PSG 1", "PSG 2", "PSG 3", "ADPCM-A 1", "ADPCM-A 2", "ADPCM-A 3", "ADPCM-A 4", "ADPCM-A 5", "ADPCM-A 6", "ADPCM-B"},
|
{"FM 1", "FM 2 OP1", "FM 2 OP2", "FM 2 OP3", "FM 2 OP4", "FM 3", "FM 4", "PSG 1", "PSG 2", "PSG 3", "ADPCM-A 1", "ADPCM-A 2", "ADPCM-A 3", "ADPCM-A 4", "ADPCM-A 5", "ADPCM-A 6", "ADPCM-B"},
|
||||||
{"F1", "O1", "O2", "O3", "O4", "F3", "F4", "S1", "S2", "S3", "P1", "P2", "P3", "P4", "P5", "P6", "B"},
|
{"F1", "O1", "O2", "O3", "O4", "F3", "F4", "S1", "S2", "S3", "P1", "P2", "P3", "P4", "P5", "P6", "B"},
|
||||||
{DIV_CH_FM, DIV_CH_OP, DIV_CH_OP, DIV_CH_OP, DIV_CH_OP, DIV_CH_FM, DIV_CH_FM, DIV_CH_PULSE, DIV_CH_PULSE, DIV_CH_PULSE, DIV_CH_PCM, DIV_CH_PCM, DIV_CH_PCM, DIV_CH_PCM, DIV_CH_PCM, DIV_CH_PCM, DIV_CH_PCM},
|
{DIV_CH_FM, DIV_CH_OP, DIV_CH_OP, DIV_CH_OP, DIV_CH_OP, DIV_CH_FM, DIV_CH_FM, DIV_CH_PULSE, DIV_CH_PULSE, DIV_CH_PULSE, DIV_CH_PCM, DIV_CH_PCM, DIV_CH_PCM, DIV_CH_PCM, DIV_CH_PCM, DIV_CH_PCM, DIV_CH_PCM},
|
||||||
|
|
@ -1542,6 +1623,7 @@ void DivEngine::registerSystems() {
|
||||||
|
|
||||||
sysDefs[DIV_SYSTEM_OPLL_DRUMS]=new DivSysDef(
|
sysDefs[DIV_SYSTEM_OPLL_DRUMS]=new DivSysDef(
|
||||||
"Yamaha YM2413 (OPLL) with drums", NULL, 0xa7, 0, 11, true, false, 0x150, false,
|
"Yamaha YM2413 (OPLL) with drums", NULL, 0xa7, 0, 11, true, false, 0x150, false,
|
||||||
|
"the OPLL chips but with drums mode turned on.",
|
||||||
{"FM 1", "FM 2", "FM 3", "FM 4", "FM 5", "FM 6", "Kick", "Snare", "Tom", "Top", "HiHat"},
|
{"FM 1", "FM 2", "FM 3", "FM 4", "FM 5", "FM 6", "Kick", "Snare", "Tom", "Top", "HiHat"},
|
||||||
{"F1", "F2", "F3", "F4", "F5", "F6", "BD", "SD", "TM", "TP", "HH"},
|
{"F1", "F2", "F3", "F4", "F5", "F6", "BD", "SD", "TM", "TP", "HH"},
|
||||||
{DIV_CH_FM, DIV_CH_FM, DIV_CH_FM, DIV_CH_FM, DIV_CH_FM, DIV_CH_FM, DIV_CH_NOISE, DIV_CH_NOISE, DIV_CH_NOISE, DIV_CH_NOISE, DIV_CH_NOISE},
|
{DIV_CH_FM, DIV_CH_FM, DIV_CH_FM, DIV_CH_FM, DIV_CH_FM, DIV_CH_FM, DIV_CH_NOISE, DIV_CH_NOISE, DIV_CH_NOISE, DIV_CH_NOISE, DIV_CH_NOISE},
|
||||||
|
|
@ -1553,6 +1635,7 @@ void DivEngine::registerSystems() {
|
||||||
|
|
||||||
sysDefs[DIV_SYSTEM_LYNX]=new DivSysDef(
|
sysDefs[DIV_SYSTEM_LYNX]=new DivSysDef(
|
||||||
"Atari Lynx", NULL, 0xa8, 0, 4, false, true, 0, false,
|
"Atari Lynx", NULL, 0xa8, 0, 4, false, true, 0, false,
|
||||||
|
"a portable console made by Atari. it has all of Atari's trademark waveforms.",
|
||||||
{"Channel 1", "Channel 2", "Channel 3", "Channel 4"},
|
{"Channel 1", "Channel 2", "Channel 3", "Channel 4"},
|
||||||
{"CH1", "CH2", "CH3", "CH4"},
|
{"CH1", "CH2", "CH3", "CH4"},
|
||||||
{DIV_CH_WAVE, DIV_CH_WAVE, DIV_CH_WAVE, DIV_CH_WAVE},
|
{DIV_CH_WAVE, DIV_CH_WAVE, DIV_CH_WAVE, DIV_CH_WAVE},
|
||||||
|
|
@ -1571,6 +1654,7 @@ void DivEngine::registerSystems() {
|
||||||
|
|
||||||
sysDefs[DIV_SYSTEM_QSOUND]=new DivSysDef(
|
sysDefs[DIV_SYSTEM_QSOUND]=new DivSysDef(
|
||||||
"Capcom QSound", NULL, 0xe0, 0, 19, false, true, 0x161, false,
|
"Capcom QSound", NULL, 0xe0, 0, 19, false, true, 0x161, false,
|
||||||
|
"used in some of Capcom's arcade boards. surround-like sampled sound with echo.",
|
||||||
{"PCM 1", "PCM 2", "PCM 3", "PCM 4", "PCM 5", "PCM 6", "PCM 7", "PCM 8", "PCM 9", "PCM 10", "PCM 11", "PCM 12", "PCM 13", "PCM 14", "PCM 15", "PCM 16", "ADPCM 1", "ADPCM 2", "ADPCM 3"},
|
{"PCM 1", "PCM 2", "PCM 3", "PCM 4", "PCM 5", "PCM 6", "PCM 7", "PCM 8", "PCM 9", "PCM 10", "PCM 11", "PCM 12", "PCM 13", "PCM 14", "PCM 15", "PCM 16", "ADPCM 1", "ADPCM 2", "ADPCM 3"},
|
||||||
{"1", "2", "3", "4", "5", "6", "7", "8", "9", "10", "11", "12", "13", "14", "15", "16", "A1", "A2", "A3"},
|
{"1", "2", "3", "4", "5", "6", "7", "8", "9", "10", "11", "12", "13", "14", "15", "16", "A1", "A2", "A3"},
|
||||||
{DIV_CH_PCM, DIV_CH_PCM, DIV_CH_PCM, DIV_CH_PCM, DIV_CH_PCM, DIV_CH_PCM, DIV_CH_PCM, DIV_CH_PCM, DIV_CH_PCM, DIV_CH_PCM, DIV_CH_PCM, DIV_CH_PCM, DIV_CH_PCM, DIV_CH_PCM, DIV_CH_PCM, DIV_CH_PCM, DIV_CH_NOISE, DIV_CH_NOISE, DIV_CH_NOISE},
|
{DIV_CH_PCM, DIV_CH_PCM, DIV_CH_PCM, DIV_CH_PCM, DIV_CH_PCM, DIV_CH_PCM, DIV_CH_PCM, DIV_CH_PCM, DIV_CH_PCM, DIV_CH_PCM, DIV_CH_PCM, DIV_CH_PCM, DIV_CH_PCM, DIV_CH_PCM, DIV_CH_PCM, DIV_CH_PCM, DIV_CH_NOISE, DIV_CH_NOISE, DIV_CH_NOISE},
|
||||||
|
|
@ -1601,6 +1685,7 @@ void DivEngine::registerSystems() {
|
||||||
|
|
||||||
sysDefs[DIV_SYSTEM_VERA]=new DivSysDef(
|
sysDefs[DIV_SYSTEM_VERA]=new DivSysDef(
|
||||||
"VERA", NULL, 0xac, 0, 17, false, true, 0, false,
|
"VERA", NULL, 0xac, 0, 17, false, true, 0, false,
|
||||||
|
"the chip used in a computer design created by The 8-Bit Guy.",
|
||||||
{"Channel 1", "Channel 2", "Channel 3", "Channel 4", "Channel 5", "Channel 6", "Channel 7", "Channel 8", "Channel 9", "Channel 10", "Channel 11", "Channel 12", "Channel 13", "Channel 14", "Channel 15", "Channel 16", "PCM"},
|
{"Channel 1", "Channel 2", "Channel 3", "Channel 4", "Channel 5", "Channel 6", "Channel 7", "Channel 8", "Channel 9", "Channel 10", "Channel 11", "Channel 12", "Channel 13", "Channel 14", "Channel 15", "Channel 16", "PCM"},
|
||||||
{"1", "2", "3", "4", "5", "6", "7", "8", "9", "10", "11", "12", "13", "14", "15", "16", "PCM"},
|
{"1", "2", "3", "4", "5", "6", "7", "8", "9", "10", "11", "12", "13", "14", "15", "16", "PCM"},
|
||||||
{DIV_CH_PULSE, DIV_CH_PULSE, DIV_CH_PULSE, DIV_CH_PULSE, DIV_CH_PULSE, DIV_CH_PULSE, DIV_CH_PULSE, DIV_CH_PULSE, DIV_CH_PULSE, DIV_CH_PULSE, DIV_CH_PULSE, DIV_CH_PULSE, DIV_CH_PULSE, DIV_CH_PULSE, DIV_CH_PULSE, DIV_CH_PULSE, DIV_CH_PCM},
|
{DIV_CH_PULSE, DIV_CH_PULSE, DIV_CH_PULSE, DIV_CH_PULSE, DIV_CH_PULSE, DIV_CH_PULSE, DIV_CH_PULSE, DIV_CH_PULSE, DIV_CH_PULSE, DIV_CH_PULSE, DIV_CH_PULSE, DIV_CH_PULSE, DIV_CH_PULSE, DIV_CH_PULSE, DIV_CH_PULSE, DIV_CH_PULSE, DIV_CH_PCM},
|
||||||
|
|
@ -1623,6 +1708,7 @@ void DivEngine::registerSystems() {
|
||||||
|
|
||||||
sysDefs[DIV_SYSTEM_YM2610B_EXT]=new DivSysDef(
|
sysDefs[DIV_SYSTEM_YM2610B_EXT]=new DivSysDef(
|
||||||
"Yamaha YM2610B (OPNB-B) Extended Channel 3", NULL, 0xde, 0, 19, true, false, 0x151, false,
|
"Yamaha YM2610B (OPNB-B) Extended Channel 3", NULL, 0xde, 0, 19, true, false, 0x151, false,
|
||||||
|
"so Taito asked Yamaha if they could get the two missing FM channels back, and Yamaha gladly provided them with this chip.\nthis one is in Extended Channel mode, which turns the second FM channel into four operators with independent notes/frequencies.",
|
||||||
{"FM 1", "FM 2", "FM 3 OP1", "FM 3 OP2", "FM 3 OP3", "FM 3 OP4", "FM 4", "FM 5", "FM 6", "PSG 1", "PSG 2", "PSG 3", "ADPCM-A 1", "ADPCM-A 2", "ADPCM-A 3", "ADPCM-A 4", "ADPCM-A 5", "ADPCM-A 6", "ADPCM-B"},
|
{"FM 1", "FM 2", "FM 3 OP1", "FM 3 OP2", "FM 3 OP3", "FM 3 OP4", "FM 4", "FM 5", "FM 6", "PSG 1", "PSG 2", "PSG 3", "ADPCM-A 1", "ADPCM-A 2", "ADPCM-A 3", "ADPCM-A 4", "ADPCM-A 5", "ADPCM-A 6", "ADPCM-B"},
|
||||||
{"F1", "F2", "O1", "O2", "O3", "O4", "F4", "F5", "F6", "S1", "S2", "S3", "P1", "P2", "P3", "P4", "P5", "P6", "B"},
|
{"F1", "F2", "O1", "O2", "O3", "O4", "F4", "F5", "F6", "S1", "S2", "S3", "P1", "P2", "P3", "P4", "P5", "P6", "B"},
|
||||||
{DIV_CH_FM, DIV_CH_FM, DIV_CH_OP, DIV_CH_OP, DIV_CH_OP, DIV_CH_OP, DIV_CH_FM, DIV_CH_FM, DIV_CH_FM, DIV_CH_PULSE, DIV_CH_PULSE, DIV_CH_PULSE, DIV_CH_PCM, DIV_CH_PCM, DIV_CH_PCM, DIV_CH_PCM, DIV_CH_PCM, DIV_CH_PCM, DIV_CH_PCM},
|
{DIV_CH_FM, DIV_CH_FM, DIV_CH_OP, DIV_CH_OP, DIV_CH_OP, DIV_CH_OP, DIV_CH_FM, DIV_CH_FM, DIV_CH_FM, DIV_CH_PULSE, DIV_CH_PULSE, DIV_CH_PULSE, DIV_CH_PCM, DIV_CH_PCM, DIV_CH_PCM, DIV_CH_PCM, DIV_CH_PCM, DIV_CH_PCM, DIV_CH_PCM},
|
||||||
|
|
@ -1634,6 +1720,7 @@ void DivEngine::registerSystems() {
|
||||||
|
|
||||||
sysDefs[DIV_SYSTEM_SEGAPCM_COMPAT]=new DivSysDef(
|
sysDefs[DIV_SYSTEM_SEGAPCM_COMPAT]=new DivSysDef(
|
||||||
"SegaPCM (compatible 5-channel mode)", NULL, 0xa9, 0, 5, false, true, 0x151, false,
|
"SegaPCM (compatible 5-channel mode)", NULL, 0xa9, 0, 5, false, true, 0x151, false,
|
||||||
|
"this is the same thing as SegaPCM, but only exposes 5 of the channels for compatibility with DefleMask.",
|
||||||
{"Channel 1", "Channel 2", "Channel 3", "Channel 4", "Channel 5"},
|
{"Channel 1", "Channel 2", "Channel 3", "Channel 4", "Channel 5"},
|
||||||
{"P1", "P2", "P3", "P4", "P5"},
|
{"P1", "P2", "P3", "P4", "P5"},
|
||||||
{DIV_CH_PCM, DIV_CH_PCM, DIV_CH_PCM, DIV_CH_PCM, DIV_CH_PCM},
|
{DIV_CH_PCM, DIV_CH_PCM, DIV_CH_PCM, DIV_CH_PCM, DIV_CH_PCM},
|
||||||
|
|
@ -1645,6 +1732,7 @@ void DivEngine::registerSystems() {
|
||||||
|
|
||||||
sysDefs[DIV_SYSTEM_X1_010]=new DivSysDef(
|
sysDefs[DIV_SYSTEM_X1_010]=new DivSysDef(
|
||||||
"Seta/Allumer X1-010", NULL, 0xb0, 0, 16, false, true, 0x171, false,
|
"Seta/Allumer X1-010", NULL, 0xb0, 0, 16, false, true, 0x171, false,
|
||||||
|
"a sound chip used in several Seta/Allumer-manufactured arcade boards with too many channels of wavetable sound, which also are capable of sampled sound.",
|
||||||
{"Channel 1", "Channel 2", "Channel 3", "Channel 4", "Channel 5", "Channel 6", "Channel 7", "Channel 8", "Channel 9", "Channel 10", "Channel 11", "Channel 12", "Channel 13", "Channel 14", "Channel 15", "Channel 16"},
|
{"Channel 1", "Channel 2", "Channel 3", "Channel 4", "Channel 5", "Channel 6", "Channel 7", "Channel 8", "Channel 9", "Channel 10", "Channel 11", "Channel 12", "Channel 13", "Channel 14", "Channel 15", "Channel 16"},
|
||||||
{"1", "2", "3", "4", "5", "6", "7", "8", "9", "10", "11", "12", "13", "14", "15", "16"},
|
{"1", "2", "3", "4", "5", "6", "7", "8", "9", "10", "11", "12", "13", "14", "15", "16"},
|
||||||
{DIV_CH_WAVE, DIV_CH_WAVE, DIV_CH_WAVE, DIV_CH_WAVE, DIV_CH_WAVE, DIV_CH_WAVE, DIV_CH_WAVE, DIV_CH_WAVE, DIV_CH_WAVE, DIV_CH_WAVE, DIV_CH_WAVE, DIV_CH_WAVE, DIV_CH_WAVE, DIV_CH_WAVE, DIV_CH_WAVE, DIV_CH_WAVE},
|
{DIV_CH_WAVE, DIV_CH_WAVE, DIV_CH_WAVE, DIV_CH_WAVE, DIV_CH_WAVE, DIV_CH_WAVE, DIV_CH_WAVE, DIV_CH_WAVE, DIV_CH_WAVE, DIV_CH_WAVE, DIV_CH_WAVE, DIV_CH_WAVE, DIV_CH_WAVE, DIV_CH_WAVE, DIV_CH_WAVE, DIV_CH_WAVE},
|
||||||
|
|
@ -1695,6 +1783,7 @@ void DivEngine::registerSystems() {
|
||||||
|
|
||||||
sysDefs[DIV_SYSTEM_BUBSYS_WSG]=new DivSysDef(
|
sysDefs[DIV_SYSTEM_BUBSYS_WSG]=new DivSysDef(
|
||||||
"Konami Bubble System WSG", NULL, 0xad, 0, 2, false, true, 0, false,
|
"Konami Bubble System WSG", NULL, 0xad, 0, 2, false, true, 0, false,
|
||||||
|
"this is the wavetable part of the Bubble System, which also had two AY-3-8910s.",
|
||||||
{"Channel 1", "Channel 2"},
|
{"Channel 1", "Channel 2"},
|
||||||
{"CH1", "CH2"},
|
{"CH1", "CH2"},
|
||||||
{DIV_CH_WAVE, DIV_CH_WAVE},
|
{DIV_CH_WAVE, DIV_CH_WAVE},
|
||||||
|
|
@ -1706,6 +1795,7 @@ void DivEngine::registerSystems() {
|
||||||
// to Grauw: feel free to change this to 24 during development of OPL4's PCM part.
|
// to Grauw: feel free to change this to 24 during development of OPL4's PCM part.
|
||||||
sysDefs[DIV_SYSTEM_OPL4]=new DivSysDef(
|
sysDefs[DIV_SYSTEM_OPL4]=new DivSysDef(
|
||||||
"Yamaha OPL4", NULL, 0xae, 0, 42, true, true, 0, false,
|
"Yamaha OPL4", NULL, 0xae, 0, 42, true, true, 0, false,
|
||||||
|
"like OPL3, but this time it also has a 24-channel version of MultiPCM.",
|
||||||
{"4OP 1", "FM 2", "4OP 3", "FM 4", "4OP 5", "FM 6", "4OP 7", "FM 8", "4OP 9", "FM 10", "4OP 11", "FM 12", "FM 13", "FM 14", "FM 15", "FM 16", "FM 17", "FM 18", "PCM 1", "PCM 2", "PCM 3", "PCM 4", "PCM 5", "PCM 6", "PCM 7", "PCM 8", "PCM 9", "PCM 10", "PCM 11", "PCM 12", "PCM 13", "PCM 14", "PCM 15", "PCM 16", "PCM 17", "PCM 18", "PCM 19", "PCM 20", "PCM 21", "PCM 22", "PCM 23", "PCM 24"},
|
{"4OP 1", "FM 2", "4OP 3", "FM 4", "4OP 5", "FM 6", "4OP 7", "FM 8", "4OP 9", "FM 10", "4OP 11", "FM 12", "FM 13", "FM 14", "FM 15", "FM 16", "FM 17", "FM 18", "PCM 1", "PCM 2", "PCM 3", "PCM 4", "PCM 5", "PCM 6", "PCM 7", "PCM 8", "PCM 9", "PCM 10", "PCM 11", "PCM 12", "PCM 13", "PCM 14", "PCM 15", "PCM 16", "PCM 17", "PCM 18", "PCM 19", "PCM 20", "PCM 21", "PCM 22", "PCM 23", "PCM 24"},
|
||||||
{"F1", "F2", "F3", "F4", "F5", "F6", "F7", "F8", "F9", "F10", "F11", "F12", "F13", "F14", "F15", "F16", "F17", "F18", "P1", "P2", "P3", "P4", "P5", "P6", "P7", "P8", "P8", "P10", "P11", "P12", "P13", "P14", "P15", "P16", "P17", "P18", "P19", "P20", "P21", "P22", "P23", "P24"},
|
{"F1", "F2", "F3", "F4", "F5", "F6", "F7", "F8", "F9", "F10", "F11", "F12", "F13", "F14", "F15", "F16", "F17", "F18", "P1", "P2", "P3", "P4", "P5", "P6", "P7", "P8", "P8", "P10", "P11", "P12", "P13", "P14", "P15", "P16", "P17", "P18", "P19", "P20", "P21", "P22", "P23", "P24"},
|
||||||
{DIV_CH_OP, DIV_CH_FM, DIV_CH_OP, DIV_CH_FM, DIV_CH_OP, DIV_CH_FM, DIV_CH_OP, DIV_CH_FM, DIV_CH_OP, DIV_CH_FM, DIV_CH_OP, DIV_CH_FM, DIV_CH_FM, DIV_CH_FM, DIV_CH_FM, DIV_CH_FM, DIV_CH_FM, DIV_CH_FM, DIV_CH_PCM, DIV_CH_PCM, DIV_CH_PCM, DIV_CH_PCM, DIV_CH_PCM, DIV_CH_PCM, DIV_CH_PCM, DIV_CH_PCM, DIV_CH_PCM, DIV_CH_PCM, DIV_CH_PCM, DIV_CH_PCM, DIV_CH_PCM, DIV_CH_PCM, DIV_CH_PCM, DIV_CH_PCM, DIV_CH_PCM, DIV_CH_PCM, DIV_CH_PCM, DIV_CH_PCM, DIV_CH_PCM, DIV_CH_PCM, DIV_CH_PCM, DIV_CH_PCM},
|
{DIV_CH_OP, DIV_CH_FM, DIV_CH_OP, DIV_CH_FM, DIV_CH_OP, DIV_CH_FM, DIV_CH_OP, DIV_CH_FM, DIV_CH_OP, DIV_CH_FM, DIV_CH_OP, DIV_CH_FM, DIV_CH_FM, DIV_CH_FM, DIV_CH_FM, DIV_CH_FM, DIV_CH_FM, DIV_CH_FM, DIV_CH_PCM, DIV_CH_PCM, DIV_CH_PCM, DIV_CH_PCM, DIV_CH_PCM, DIV_CH_PCM, DIV_CH_PCM, DIV_CH_PCM, DIV_CH_PCM, DIV_CH_PCM, DIV_CH_PCM, DIV_CH_PCM, DIV_CH_PCM, DIV_CH_PCM, DIV_CH_PCM, DIV_CH_PCM, DIV_CH_PCM, DIV_CH_PCM, DIV_CH_PCM, DIV_CH_PCM, DIV_CH_PCM, DIV_CH_PCM, DIV_CH_PCM, DIV_CH_PCM},
|
||||||
|
|
@ -1714,6 +1804,7 @@ void DivEngine::registerSystems() {
|
||||||
|
|
||||||
sysDefs[DIV_SYSTEM_OPL4_DRUMS]=new DivSysDef(
|
sysDefs[DIV_SYSTEM_OPL4_DRUMS]=new DivSysDef(
|
||||||
"Yamaha OPL4 with drums", NULL, 0xaf, 0, 44, true, true, 0, false,
|
"Yamaha OPL4 with drums", NULL, 0xaf, 0, 44, true, true, 0, false,
|
||||||
|
"the OPL4 but with drums mode turned on.",
|
||||||
{"4OP 1", "FM 2", "4OP 3", "FM 4", "4OP 5", "FM 6", "4OP 7", "FM 8", "4OP 9", "FM 10", "4OP 11", "FM 12", "FM 13", "FM 14", "FM 15", "Kick", "Snare", "Tom", "Top", "HiHat", "PCM 1", "PCM 2", "PCM 3", "PCM 4", "PCM 5", "PCM 6", "PCM 7", "PCM 8", "PCM 9", "PCM 10", "PCM 11", "PCM 12", "PCM 13", "PCM 14", "PCM 15", "PCM 16", "PCM 17", "PCM 18", "PCM 19", "PCM 20", "PCM 21", "PCM 22", "PCM 23", "PCM 24"},
|
{"4OP 1", "FM 2", "4OP 3", "FM 4", "4OP 5", "FM 6", "4OP 7", "FM 8", "4OP 9", "FM 10", "4OP 11", "FM 12", "FM 13", "FM 14", "FM 15", "Kick", "Snare", "Tom", "Top", "HiHat", "PCM 1", "PCM 2", "PCM 3", "PCM 4", "PCM 5", "PCM 6", "PCM 7", "PCM 8", "PCM 9", "PCM 10", "PCM 11", "PCM 12", "PCM 13", "PCM 14", "PCM 15", "PCM 16", "PCM 17", "PCM 18", "PCM 19", "PCM 20", "PCM 21", "PCM 22", "PCM 23", "PCM 24"},
|
||||||
{"F1", "F2", "F3", "F4", "F5", "F6", "F7", "F8", "F9", "F10", "F11", "F12", "F13", "F14", "F15", "BD", "SD", "TM", "TP", "HH", "P1", "P2", "P3", "P4", "P5", "P6", "P7", "P8", "P8", "P10", "P11", "P12", "P13", "P14", "P15", "P16", "P17", "P18", "P19", "P20", "P21", "P22", "P23", "P24"},
|
{"F1", "F2", "F3", "F4", "F5", "F6", "F7", "F8", "F9", "F10", "F11", "F12", "F13", "F14", "F15", "BD", "SD", "TM", "TP", "HH", "P1", "P2", "P3", "P4", "P5", "P6", "P7", "P8", "P8", "P10", "P11", "P12", "P13", "P14", "P15", "P16", "P17", "P18", "P19", "P20", "P21", "P22", "P23", "P24"},
|
||||||
{DIV_CH_OP, DIV_CH_FM, DIV_CH_OP, DIV_CH_FM, DIV_CH_OP, DIV_CH_FM, DIV_CH_OP, DIV_CH_FM, DIV_CH_OP, DIV_CH_FM, DIV_CH_OP, DIV_CH_FM, DIV_CH_FM, DIV_CH_FM, DIV_CH_FM, DIV_CH_NOISE, DIV_CH_NOISE, DIV_CH_NOISE, DIV_CH_NOISE, DIV_CH_NOISE, DIV_CH_PCM, DIV_CH_PCM, DIV_CH_PCM, DIV_CH_PCM, DIV_CH_PCM, DIV_CH_PCM, DIV_CH_PCM, DIV_CH_PCM, DIV_CH_PCM, DIV_CH_PCM, DIV_CH_PCM, DIV_CH_PCM, DIV_CH_PCM, DIV_CH_PCM, DIV_CH_PCM, DIV_CH_PCM, DIV_CH_PCM, DIV_CH_PCM, DIV_CH_PCM, DIV_CH_PCM, DIV_CH_PCM, DIV_CH_PCM, DIV_CH_PCM, DIV_CH_PCM},
|
{DIV_CH_OP, DIV_CH_FM, DIV_CH_OP, DIV_CH_FM, DIV_CH_OP, DIV_CH_FM, DIV_CH_OP, DIV_CH_FM, DIV_CH_OP, DIV_CH_FM, DIV_CH_OP, DIV_CH_FM, DIV_CH_FM, DIV_CH_FM, DIV_CH_FM, DIV_CH_NOISE, DIV_CH_NOISE, DIV_CH_NOISE, DIV_CH_NOISE, DIV_CH_NOISE, DIV_CH_PCM, DIV_CH_PCM, DIV_CH_PCM, DIV_CH_PCM, DIV_CH_PCM, DIV_CH_PCM, DIV_CH_PCM, DIV_CH_PCM, DIV_CH_PCM, DIV_CH_PCM, DIV_CH_PCM, DIV_CH_PCM, DIV_CH_PCM, DIV_CH_PCM, DIV_CH_PCM, DIV_CH_PCM, DIV_CH_PCM, DIV_CH_PCM, DIV_CH_PCM, DIV_CH_PCM, DIV_CH_PCM, DIV_CH_PCM, DIV_CH_PCM, DIV_CH_PCM},
|
||||||
|
|
@ -1722,6 +1813,7 @@ void DivEngine::registerSystems() {
|
||||||
|
|
||||||
sysDefs[DIV_SYSTEM_ES5506]=new DivSysDef(
|
sysDefs[DIV_SYSTEM_ES5506]=new DivSysDef(
|
||||||
"Ensoniq ES5506", NULL, 0xb1, 0, 32, false, true, 0, false,
|
"Ensoniq ES5506", NULL, 0xb1, 0, 32, false, true, 0, false,
|
||||||
|
"a sample chip used in the Gravis Ultrasound, popular in the PC (DOS) demoscene.",
|
||||||
{"Channel 1", "Channel 2", "Channel 3", "Channel 4", "Channel 5", "Channel 6", "Channel 7", "Channel 8", "Channel 9", "Channel 10", "Channel 11", "Channel 12", "Channel 13", "Channel 14", "Channel 15", "Channel 16", "Channel 17", "Channel 18", "Channel 19", "Channel 20", "Channel 21", "Channel 22", "Channel 23", "Channel 24", "Channel 25", "Channel 26", "Channel 27", "Channel 28", "Channel 29", "Channel 30", "Channel 31", "Channel 32"},
|
{"Channel 1", "Channel 2", "Channel 3", "Channel 4", "Channel 5", "Channel 6", "Channel 7", "Channel 8", "Channel 9", "Channel 10", "Channel 11", "Channel 12", "Channel 13", "Channel 14", "Channel 15", "Channel 16", "Channel 17", "Channel 18", "Channel 19", "Channel 20", "Channel 21", "Channel 22", "Channel 23", "Channel 24", "Channel 25", "Channel 26", "Channel 27", "Channel 28", "Channel 29", "Channel 30", "Channel 31", "Channel 32"},
|
||||||
{"1", "2", "3", "4", "5", "6", "7", "8", "9", "10", "11", "12", "13", "14", "15", "16", "17", "18", "19", "20", "21", "22", "23", "24", "25", "26", "27", "28", "29", "30", "31", "32"},
|
{"1", "2", "3", "4", "5", "6", "7", "8", "9", "10", "11", "12", "13", "14", "15", "16", "17", "18", "19", "20", "21", "22", "23", "24", "25", "26", "27", "28", "29", "30", "31", "32"},
|
||||||
{DIV_CH_PCM, DIV_CH_PCM, DIV_CH_PCM, DIV_CH_PCM, DIV_CH_PCM, DIV_CH_PCM, DIV_CH_PCM, DIV_CH_PCM, DIV_CH_PCM, DIV_CH_PCM, DIV_CH_PCM, DIV_CH_PCM, DIV_CH_PCM, DIV_CH_PCM, DIV_CH_PCM, DIV_CH_PCM, DIV_CH_PCM, DIV_CH_PCM, DIV_CH_PCM, DIV_CH_PCM, DIV_CH_PCM, DIV_CH_PCM, DIV_CH_PCM, DIV_CH_PCM, DIV_CH_PCM, DIV_CH_PCM, DIV_CH_PCM, DIV_CH_PCM, DIV_CH_PCM, DIV_CH_PCM, DIV_CH_PCM, DIV_CH_PCM},
|
{DIV_CH_PCM, DIV_CH_PCM, DIV_CH_PCM, DIV_CH_PCM, DIV_CH_PCM, DIV_CH_PCM, DIV_CH_PCM, DIV_CH_PCM, DIV_CH_PCM, DIV_CH_PCM, DIV_CH_PCM, DIV_CH_PCM, DIV_CH_PCM, DIV_CH_PCM, DIV_CH_PCM, DIV_CH_PCM, DIV_CH_PCM, DIV_CH_PCM, DIV_CH_PCM, DIV_CH_PCM, DIV_CH_PCM, DIV_CH_PCM, DIV_CH_PCM, DIV_CH_PCM, DIV_CH_PCM, DIV_CH_PCM, DIV_CH_PCM, DIV_CH_PCM, DIV_CH_PCM, DIV_CH_PCM, DIV_CH_PCM, DIV_CH_PCM},
|
||||||
|
|
@ -1730,22 +1822,31 @@ void DivEngine::registerSystems() {
|
||||||
|
|
||||||
sysDefs[DIV_SYSTEM_Y8950]=new DivSysDef(
|
sysDefs[DIV_SYSTEM_Y8950]=new DivSysDef(
|
||||||
"Yamaha Y8950", NULL, 0xb2, 0, 10, true, false, 0, false,
|
"Yamaha Y8950", NULL, 0xb2, 0, 10, true, false, 0, false,
|
||||||
|
"like OPL but with an ADPCM channel.",
|
||||||
{"FM 1", "FM 2", "FM 3", "FM 4", "FM 5", "FM 6", "FM 7", "FM 8", "FM 9", "PCM"},
|
{"FM 1", "FM 2", "FM 3", "FM 4", "FM 5", "FM 6", "FM 7", "FM 8", "FM 9", "PCM"},
|
||||||
{"F1", "F2", "F3", "F4", "F5", "F6", "F7", "F8", "F9", "PCM"},
|
{"F1", "F2", "F3", "F4", "F5", "F6", "F7", "F8", "F9", "PCM"},
|
||||||
{DIV_CH_FM, DIV_CH_FM, DIV_CH_FM, DIV_CH_FM, DIV_CH_FM, DIV_CH_FM, DIV_CH_FM, DIV_CH_FM, DIV_CH_FM, DIV_CH_PCM},
|
{DIV_CH_FM, DIV_CH_FM, DIV_CH_FM, DIV_CH_FM, DIV_CH_FM, DIV_CH_FM, DIV_CH_FM, DIV_CH_FM, DIV_CH_FM, DIV_CH_PCM},
|
||||||
{DIV_INS_OPL, DIV_INS_OPL, DIV_INS_OPL, DIV_INS_OPL, DIV_INS_OPL, DIV_INS_OPL, DIV_INS_OPL, DIV_INS_OPL, DIV_INS_OPL, DIV_INS_AMIGA}
|
{DIV_INS_OPL, DIV_INS_OPL, DIV_INS_OPL, DIV_INS_OPL, DIV_INS_OPL, DIV_INS_OPL, DIV_INS_OPL, DIV_INS_OPL, DIV_INS_OPL, DIV_INS_AMIGA},
|
||||||
|
{},
|
||||||
|
oplEffectHandler,
|
||||||
|
fmOPLPostEffectHandler
|
||||||
);
|
);
|
||||||
|
|
||||||
sysDefs[DIV_SYSTEM_Y8950_DRUMS]=new DivSysDef(
|
sysDefs[DIV_SYSTEM_Y8950_DRUMS]=new DivSysDef(
|
||||||
"Yamaha Y8950 with drums", NULL, 0xb3, 0, 12, true, false, 0, false,
|
"Yamaha Y8950 with drums", NULL, 0xb3, 0, 12, true, false, 0, false,
|
||||||
|
"the Y8950 chip, in drums mode.",
|
||||||
{"FM 1", "FM 2", "FM 3", "FM 4", "FM 5", "FM 6", "Kick", "Snare", "Tom", "Top", "HiHat", "PCM"},
|
{"FM 1", "FM 2", "FM 3", "FM 4", "FM 5", "FM 6", "Kick", "Snare", "Tom", "Top", "HiHat", "PCM"},
|
||||||
{"F1", "F2", "F3", "F4", "F5", "F6", "BD", "SD", "TM", "TP", "HH", "PCM"},
|
{"F1", "F2", "F3", "F4", "F5", "F6", "BD", "SD", "TM", "TP", "HH", "PCM"},
|
||||||
{DIV_CH_FM, DIV_CH_FM, DIV_CH_FM, DIV_CH_FM, DIV_CH_FM, DIV_CH_FM, DIV_CH_NOISE, DIV_CH_NOISE, DIV_CH_NOISE, DIV_CH_NOISE, DIV_CH_NOISE, DIV_CH_PCM},
|
{DIV_CH_FM, DIV_CH_FM, DIV_CH_FM, DIV_CH_FM, DIV_CH_FM, DIV_CH_FM, DIV_CH_NOISE, DIV_CH_NOISE, DIV_CH_NOISE, DIV_CH_NOISE, DIV_CH_NOISE, DIV_CH_PCM},
|
||||||
{DIV_INS_OPL, DIV_INS_OPL, DIV_INS_OPL, DIV_INS_OPL, DIV_INS_OPL, DIV_INS_OPL, DIV_INS_OPL, DIV_INS_OPL, DIV_INS_OPL, DIV_INS_OPL, DIV_INS_OPL, DIV_INS_AMIGA}
|
{DIV_INS_OPL, DIV_INS_OPL, DIV_INS_OPL, DIV_INS_OPL, DIV_INS_OPL, DIV_INS_OPL, DIV_INS_OPL, DIV_INS_OPL, DIV_INS_OPL, DIV_INS_OPL, DIV_INS_OPL, DIV_INS_AMIGA},
|
||||||
|
{},
|
||||||
|
oplEffectHandler,
|
||||||
|
fmOPLPostEffectHandler
|
||||||
);
|
);
|
||||||
|
|
||||||
sysDefs[DIV_SYSTEM_SCC_PLUS]=new DivSysDef(
|
sysDefs[DIV_SYSTEM_SCC_PLUS]=new DivSysDef(
|
||||||
"Konami SCC+", NULL, 0xb4, 0, 5, false, true, 0x161, false,
|
"Konami SCC+", NULL, 0xb4, 0, 5, false, true, 0x161, false,
|
||||||
|
"this is a variant of Konami's SCC chip with the last channel's wavetable being independent.",
|
||||||
{"Channel 1", "Channel 2", "Channel 3", "Channel 4", "Channel 5"},
|
{"Channel 1", "Channel 2", "Channel 3", "Channel 4", "Channel 5"},
|
||||||
{"CH1", "CH2", "CH3", "CH4", "CH5"},
|
{"CH1", "CH2", "CH3", "CH4", "CH5"},
|
||||||
{DIV_CH_WAVE, DIV_CH_WAVE, DIV_CH_WAVE, DIV_CH_WAVE, DIV_CH_WAVE},
|
{DIV_CH_WAVE, DIV_CH_WAVE, DIV_CH_WAVE, DIV_CH_WAVE, DIV_CH_WAVE},
|
||||||
|
|
@ -1756,6 +1857,7 @@ void DivEngine::registerSystems() {
|
||||||
|
|
||||||
sysDefs[DIV_SYSTEM_SOUND_UNIT]=new DivSysDef(
|
sysDefs[DIV_SYSTEM_SOUND_UNIT]=new DivSysDef(
|
||||||
"tildearrow Sound Unit", NULL, 0xb5, 0, 8, false, true, 0, false,
|
"tildearrow Sound Unit", NULL, 0xb5, 0, 8, false, true, 0, false,
|
||||||
|
"tildearrow's fantasy sound chip. put SID, AY and VERA in a blender, and you get this!",
|
||||||
{"Channel 1", "Channel 2", "Channel 3", "Channel 4", "Channel 5", "Channel 6", "Channel 7", "Channel 8"},
|
{"Channel 1", "Channel 2", "Channel 3", "Channel 4", "Channel 5", "Channel 6", "Channel 7", "Channel 8"},
|
||||||
{"CH1", "CH2", "CH3", "CH4", "CH5", "CH6", "CH7", "CH8"},
|
{"CH1", "CH2", "CH3", "CH4", "CH5", "CH6", "CH7", "CH8"},
|
||||||
{DIV_CH_NOISE, DIV_CH_NOISE, DIV_CH_NOISE, DIV_CH_NOISE, DIV_CH_NOISE, DIV_CH_NOISE, DIV_CH_NOISE, DIV_CH_NOISE},
|
{DIV_CH_NOISE, DIV_CH_NOISE, DIV_CH_NOISE, DIV_CH_NOISE, DIV_CH_NOISE, DIV_CH_NOISE, DIV_CH_NOISE, DIV_CH_NOISE},
|
||||||
|
|
@ -1765,6 +1867,7 @@ void DivEngine::registerSystems() {
|
||||||
|
|
||||||
sysDefs[DIV_SYSTEM_MSM6295]=new DivSysDef(
|
sysDefs[DIV_SYSTEM_MSM6295]=new DivSysDef(
|
||||||
"OKI MSM6295", NULL, 0xaa, 0, 4, false, true, 0, false,
|
"OKI MSM6295", NULL, 0xaa, 0, 4, false, true, 0, false,
|
||||||
|
"an ADPCM sound chip manufactured by OKI and used in many arcade boards.",
|
||||||
{"Channel 1", "Channel 2", "Channel 3", "Channel 4"},
|
{"Channel 1", "Channel 2", "Channel 3", "Channel 4"},
|
||||||
{"CH1", "CH2", "CH3", "CH4"},
|
{"CH1", "CH2", "CH3", "CH4"},
|
||||||
{DIV_CH_PCM, DIV_CH_PCM, DIV_CH_PCM, DIV_CH_PCM},
|
{DIV_CH_PCM, DIV_CH_PCM, DIV_CH_PCM, DIV_CH_PCM},
|
||||||
|
|
@ -1773,6 +1876,7 @@ void DivEngine::registerSystems() {
|
||||||
|
|
||||||
sysDefs[DIV_SYSTEM_MSM6258]=new DivSysDef(
|
sysDefs[DIV_SYSTEM_MSM6258]=new DivSysDef(
|
||||||
"OKI MSM6258", NULL, 0xab, 0, 1, false, true, 0, false,
|
"OKI MSM6258", NULL, 0xab, 0, 1, false, true, 0, false,
|
||||||
|
"an ADPCM sound chip manufactured by OKI and used in the Sharp X68000.",
|
||||||
{"Sample"},
|
{"Sample"},
|
||||||
{"PCM"},
|
{"PCM"},
|
||||||
{DIV_CH_PCM},
|
{DIV_CH_PCM},
|
||||||
|
|
@ -1781,6 +1885,7 @@ void DivEngine::registerSystems() {
|
||||||
|
|
||||||
sysDefs[DIV_SYSTEM_DUMMY]=new DivSysDef(
|
sysDefs[DIV_SYSTEM_DUMMY]=new DivSysDef(
|
||||||
"Dummy System", NULL, 0xfd, 0, 8, false, true, 0, false,
|
"Dummy System", NULL, 0xfd, 0, 8, false, true, 0, false,
|
||||||
|
"this is a system designed for testing purposes..",
|
||||||
{"Channel 1", "Channel 2", "Channel 3", "Channel 4", "Channel 5", "Channel 6", "Channel 7", "Channel 8"},
|
{"Channel 1", "Channel 2", "Channel 3", "Channel 4", "Channel 5", "Channel 6", "Channel 7", "Channel 8"},
|
||||||
{"CH1", "CH2", "CH3", "CH4", "CH5", "CH6", "CH7", "CH8"},
|
{"CH1", "CH2", "CH3", "CH4", "CH5", "CH6", "CH7", "CH8"},
|
||||||
{DIV_CH_NOISE, DIV_CH_NOISE, DIV_CH_NOISE, DIV_CH_NOISE, DIV_CH_NOISE, DIV_CH_NOISE, DIV_CH_NOISE, DIV_CH_NOISE},
|
{DIV_CH_NOISE, DIV_CH_NOISE, DIV_CH_NOISE, DIV_CH_NOISE, DIV_CH_NOISE, DIV_CH_NOISE, DIV_CH_NOISE, DIV_CH_NOISE},
|
||||||
|
|
|
||||||
|
|
@ -21,28 +21,48 @@
|
||||||
|
|
||||||
#include "actionUtil.h"
|
#include "actionUtil.h"
|
||||||
|
|
||||||
void FurnaceGUI::startSelection(int xCoarse, int xFine, int y) {
|
void FurnaceGUI::startSelection(int xCoarse, int xFine, int y, bool fullRow) {
|
||||||
|
DETERMINE_FIRST_LAST;
|
||||||
|
|
||||||
if (xCoarse!=selStart.xCoarse || xFine!=selStart.xFine || y!=selStart.y) {
|
if (xCoarse!=selStart.xCoarse || xFine!=selStart.xFine || y!=selStart.y) {
|
||||||
curNibble=false;
|
curNibble=false;
|
||||||
}
|
}
|
||||||
cursor.xCoarse=xCoarse;
|
|
||||||
cursor.xFine=xFine;
|
if (fullRow) {
|
||||||
cursor.y=y;
|
selStart.xCoarse=firstChannel;
|
||||||
selStart.xCoarse=xCoarse;
|
selStart.xFine=0;
|
||||||
selStart.xFine=xFine;
|
selEnd.xCoarse=lastChannel-1;
|
||||||
selStart.y=y;
|
selEnd.xFine=2+e->song.pat[selEnd.xCoarse].effectCols*2;
|
||||||
selEnd.xCoarse=xCoarse;
|
selStart.y=y;
|
||||||
selEnd.xFine=xFine;
|
selEnd.y=y;
|
||||||
selEnd.y=y;
|
} else {
|
||||||
|
cursor.xCoarse=xCoarse;
|
||||||
|
cursor.xFine=xFine;
|
||||||
|
cursor.y=y;
|
||||||
|
selStart.xCoarse=xCoarse;
|
||||||
|
selStart.xFine=xFine;
|
||||||
|
selStart.y=y;
|
||||||
|
selEnd.xCoarse=xCoarse;
|
||||||
|
selEnd.xFine=xFine;
|
||||||
|
selEnd.y=y;
|
||||||
|
}
|
||||||
selecting=true;
|
selecting=true;
|
||||||
|
selectingFull=fullRow;
|
||||||
e->setMidiBaseChan(cursor.xCoarse);
|
e->setMidiBaseChan(cursor.xCoarse);
|
||||||
}
|
}
|
||||||
|
|
||||||
void FurnaceGUI::updateSelection(int xCoarse, int xFine, int y) {
|
void FurnaceGUI::updateSelection(int xCoarse, int xFine, int y, bool fullRow) {
|
||||||
if (!selecting) return;
|
if (!selecting) return;
|
||||||
selEnd.xCoarse=xCoarse;
|
if (selectingFull) {
|
||||||
selEnd.xFine=xFine;
|
DETERMINE_LAST;
|
||||||
selEnd.y=y;
|
selEnd.xCoarse=lastChannel-1;
|
||||||
|
selEnd.xFine=2+e->song.pat[selEnd.xCoarse].effectCols*2;
|
||||||
|
selEnd.y=y;
|
||||||
|
} else {
|
||||||
|
selEnd.xCoarse=xCoarse;
|
||||||
|
selEnd.xFine=xFine;
|
||||||
|
selEnd.y=y;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void FurnaceGUI::finishSelection() {
|
void FurnaceGUI::finishSelection() {
|
||||||
|
|
@ -66,6 +86,7 @@ void FurnaceGUI::finishSelection() {
|
||||||
selEnd.xFine^=selStart.xFine;
|
selEnd.xFine^=selStart.xFine;
|
||||||
}
|
}
|
||||||
selecting=false;
|
selecting=false;
|
||||||
|
selectingFull=false;
|
||||||
|
|
||||||
// boundary check
|
// boundary check
|
||||||
int chanCount=e->getTotalChannelCount();
|
int chanCount=e->getTotalChannelCount();
|
||||||
|
|
|
||||||
128
src/gui/gui.cpp
128
src/gui/gui.cpp
|
|
@ -194,21 +194,6 @@ void FurnaceGUI::decodeKeyMap(std::map<int,int>& map, String source) {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void FurnaceGUI::encodeMMLStr(String& target, unsigned char* macro, unsigned char macroLen, signed char macroLoop, signed char macroRel) {
|
|
||||||
target="";
|
|
||||||
char buf[32];
|
|
||||||
for (int i=0; i<macroLen; i++) {
|
|
||||||
if (i==macroLoop) target+="| ";
|
|
||||||
if (i==macroRel) target+="/ ";
|
|
||||||
if (i==macroLen-1) {
|
|
||||||
snprintf(buf,31,"%d",macro[i]);
|
|
||||||
} else {
|
|
||||||
snprintf(buf,31,"%d ",macro[i]);
|
|
||||||
}
|
|
||||||
target+=buf;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
void FurnaceGUI::encodeMMLStr(String& target, int* macro, int macroLen, int macroLoop, int macroRel, bool hex) {
|
void FurnaceGUI::encodeMMLStr(String& target, int* macro, int macroLen, int macroLoop, int macroRel, bool hex) {
|
||||||
target="";
|
target="";
|
||||||
char buf[32];
|
char buf[32];
|
||||||
|
|
@ -290,53 +275,6 @@ void FurnaceGUI::decodeMMLStrW(String& source, int* macro, int& macroLen, int ma
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void FurnaceGUI::decodeMMLStr(String& source, unsigned char* macro, unsigned char& macroLen, signed char& macroLoop, int macroMin, int macroMax, signed char& macroRel) {
|
|
||||||
int buf=0;
|
|
||||||
bool hasVal=false;
|
|
||||||
macroLen=0;
|
|
||||||
macroLoop=-1;
|
|
||||||
macroRel=-1;
|
|
||||||
for (char& i: source) {
|
|
||||||
switch (i) {
|
|
||||||
case '0': case '1': case '2': case '3': case '4':
|
|
||||||
case '5': case '6': case '7': case '8': case '9':
|
|
||||||
hasVal=true;
|
|
||||||
buf*=10;
|
|
||||||
buf+=i-'0';
|
|
||||||
break;
|
|
||||||
case ' ':
|
|
||||||
if (hasVal) {
|
|
||||||
hasVal=false;
|
|
||||||
macro[macroLen]=buf;
|
|
||||||
if (macro[macroLen]<macroMin) macro[macroLen]=macroMin;
|
|
||||||
if (macro[macroLen]>macroMax) macro[macroLen]=macroMax;
|
|
||||||
macroLen++;
|
|
||||||
buf=0;
|
|
||||||
}
|
|
||||||
break;
|
|
||||||
case '|':
|
|
||||||
if (macroLoop==-1) {
|
|
||||||
macroLoop=macroLen;
|
|
||||||
}
|
|
||||||
break;
|
|
||||||
case '/':
|
|
||||||
if (macroRel==-1) {
|
|
||||||
macroRel=macroLen;
|
|
||||||
}
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
if (macroLen>=128) break;
|
|
||||||
}
|
|
||||||
if (hasVal && macroLen<128) {
|
|
||||||
hasVal=false;
|
|
||||||
macro[macroLen]=buf;
|
|
||||||
if (macro[macroLen]<macroMin) macro[macroLen]=macroMin;
|
|
||||||
if (macro[macroLen]>macroMax) macro[macroLen]=macroMax;
|
|
||||||
macroLen++;
|
|
||||||
buf=0;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
void FurnaceGUI::decodeMMLStr(String& source, int* macro, unsigned char& macroLen, signed char& macroLoop, int macroMin, int macroMax, signed char& macroRel) {
|
void FurnaceGUI::decodeMMLStr(String& source, int* macro, unsigned char& macroLen, signed char& macroLoop, int macroMin, int macroMax, signed char& macroRel) {
|
||||||
int buf=0;
|
int buf=0;
|
||||||
bool negaBuf=false;
|
bool negaBuf=false;
|
||||||
|
|
@ -370,11 +308,29 @@ void FurnaceGUI::decodeMMLStr(String& source, int* macro, unsigned char& macroLe
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
case '|':
|
case '|':
|
||||||
|
if (hasVal) {
|
||||||
|
hasVal=false;
|
||||||
|
macro[macroLen]=negaBuf?-buf:buf;
|
||||||
|
negaBuf=false;
|
||||||
|
if (macro[macroLen]<macroMin) macro[macroLen]=macroMin;
|
||||||
|
if (macro[macroLen]>macroMax) macro[macroLen]=macroMax;
|
||||||
|
macroLen++;
|
||||||
|
buf=0;
|
||||||
|
}
|
||||||
if (macroLoop==-1) {
|
if (macroLoop==-1) {
|
||||||
macroLoop=macroLen;
|
macroLoop=macroLen;
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
case '/':
|
case '/':
|
||||||
|
if (hasVal) {
|
||||||
|
hasVal=false;
|
||||||
|
macro[macroLen]=negaBuf?-buf:buf;
|
||||||
|
negaBuf=false;
|
||||||
|
if (macro[macroLen]<macroMin) macro[macroLen]=macroMin;
|
||||||
|
if (macro[macroLen]>macroMax) macro[macroLen]=macroMax;
|
||||||
|
macroLen++;
|
||||||
|
buf=0;
|
||||||
|
}
|
||||||
if (macroRel==-1) {
|
if (macroRel==-1) {
|
||||||
macroRel=macroLen;
|
macroRel=macroLen;
|
||||||
}
|
}
|
||||||
|
|
@ -1523,6 +1479,19 @@ void FurnaceGUI::openFileDialog(FurnaceGUIFileDialogs type) {
|
||||||
dpiScale
|
dpiScale
|
||||||
);
|
);
|
||||||
break;
|
break;
|
||||||
|
case GUI_FILE_YRW801_ROM_OPEN:
|
||||||
|
case GUI_FILE_TG100_ROM_OPEN:
|
||||||
|
case GUI_FILE_MU5_ROM_OPEN:
|
||||||
|
if (!dirExists(workingDirSample)) workingDirSample=getHomeDir();
|
||||||
|
hasOpened=fileDialog->openLoad(
|
||||||
|
"Load ROM",
|
||||||
|
{"compatible files", "*.rom *.bin",
|
||||||
|
"all files", ".*"},
|
||||||
|
"compatible files{.rom,.bin},.*",
|
||||||
|
workingDirROM,
|
||||||
|
dpiScale
|
||||||
|
);
|
||||||
|
break;
|
||||||
}
|
}
|
||||||
if (hasOpened) curFileDialog=type;
|
if (hasOpened) curFileDialog=type;
|
||||||
//ImGui::GetIO().ConfigFlags|=ImGuiConfigFlags_NavEnableKeyboard;
|
//ImGui::GetIO().ConfigFlags|=ImGuiConfigFlags_NavEnableKeyboard;
|
||||||
|
|
@ -2397,7 +2366,7 @@ bool FurnaceGUI::loop() {
|
||||||
}
|
}
|
||||||
sampleDragActive=false;
|
sampleDragActive=false;
|
||||||
if (selecting) {
|
if (selecting) {
|
||||||
cursor=selEnd;
|
if (!selectingFull) cursor=selEnd;
|
||||||
finishSelection();
|
finishSelection();
|
||||||
demandScrollX=true;
|
demandScrollX=true;
|
||||||
if (cursor.xCoarse==selStart.xCoarse && cursor.xFine==selStart.xFine && cursor.y==selStart.y &&
|
if (cursor.xCoarse==selStart.xCoarse && cursor.xFine==selStart.xFine && cursor.y==selStart.y &&
|
||||||
|
|
@ -2805,7 +2774,7 @@ bool FurnaceGUI::loop() {
|
||||||
doAction(GUI_ACTION_FULLSCREEN);
|
doAction(GUI_ACTION_FULLSCREEN);
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
if (ImGui::MenuItem("lock layout",NULL,lockLayout)) {
|
if (ImGui::MenuItem("lock layout (not working!)",NULL,lockLayout)) {
|
||||||
lockLayout=!lockLayout;
|
lockLayout=!lockLayout;
|
||||||
}
|
}
|
||||||
if (ImGui::MenuItem("visualizer",NULL,fancyPattern)) {
|
if (ImGui::MenuItem("visualizer",NULL,fancyPattern)) {
|
||||||
|
|
@ -3040,6 +3009,11 @@ bool FurnaceGUI::loop() {
|
||||||
case GUI_FILE_EXPORT_LAYOUT:
|
case GUI_FILE_EXPORT_LAYOUT:
|
||||||
workingDirLayout=fileDialog->getPath()+DIR_SEPARATOR_STR;
|
workingDirLayout=fileDialog->getPath()+DIR_SEPARATOR_STR;
|
||||||
break;
|
break;
|
||||||
|
case GUI_FILE_YRW801_ROM_OPEN:
|
||||||
|
case GUI_FILE_TG100_ROM_OPEN:
|
||||||
|
case GUI_FILE_MU5_ROM_OPEN:
|
||||||
|
workingDirROM=fileDialog->getPath()+DIR_SEPARATOR_STR;
|
||||||
|
break;
|
||||||
}
|
}
|
||||||
if (fileDialog->accepted()) {
|
if (fileDialog->accepted()) {
|
||||||
fileName=fileDialog->getFileName();
|
fileName=fileDialog->getFileName();
|
||||||
|
|
@ -3253,6 +3227,15 @@ bool FurnaceGUI::loop() {
|
||||||
case GUI_FILE_EXPORT_LAYOUT:
|
case GUI_FILE_EXPORT_LAYOUT:
|
||||||
exportLayout(copyOfName);
|
exportLayout(copyOfName);
|
||||||
break;
|
break;
|
||||||
|
case GUI_FILE_YRW801_ROM_OPEN:
|
||||||
|
settings.yrw801Path=copyOfName;
|
||||||
|
break;
|
||||||
|
case GUI_FILE_TG100_ROM_OPEN:
|
||||||
|
settings.tg100Path=copyOfName;
|
||||||
|
break;
|
||||||
|
case GUI_FILE_MU5_ROM_OPEN:
|
||||||
|
settings.mu5Path=copyOfName;
|
||||||
|
break;
|
||||||
}
|
}
|
||||||
curFileDialog=GUI_FILE_OPEN;
|
curFileDialog=GUI_FILE_OPEN;
|
||||||
}
|
}
|
||||||
|
|
@ -3305,7 +3288,7 @@ bool FurnaceGUI::loop() {
|
||||||
}
|
}
|
||||||
|
|
||||||
ImGui::SetNextWindowSizeConstraints(ImVec2(400.0f*dpiScale,200.0f*dpiScale),ImVec2(scrW*dpiScale,scrH*dpiScale));
|
ImGui::SetNextWindowSizeConstraints(ImVec2(400.0f*dpiScale,200.0f*dpiScale),ImVec2(scrW*dpiScale,scrH*dpiScale));
|
||||||
if (ImGui::BeginPopupModal("New Song",NULL,ImGuiWindowFlags_NoMove)) {
|
if (ImGui::BeginPopupModal("New Song",NULL,ImGuiWindowFlags_NoMove|ImGuiWindowFlags_NoScrollWithMouse|ImGuiWindowFlags_NoScrollbar)) {
|
||||||
ImGui::SetWindowPos(ImVec2(((scrW*dpiScale)-ImGui::GetWindowSize().x)*0.5,((scrH*dpiScale)-ImGui::GetWindowSize().y)*0.5));
|
ImGui::SetWindowPos(ImVec2(((scrW*dpiScale)-ImGui::GetWindowSize().x)*0.5,((scrH*dpiScale)-ImGui::GetWindowSize().y)*0.5));
|
||||||
drawNewSong();
|
drawNewSong();
|
||||||
ImGui::EndPopup();
|
ImGui::EndPopup();
|
||||||
|
|
@ -3690,6 +3673,12 @@ bool FurnaceGUI::init() {
|
||||||
fullScreen=e->getConfBool("fullScreen",false);
|
fullScreen=e->getConfBool("fullScreen",false);
|
||||||
#endif
|
#endif
|
||||||
mobileUI=e->getConfBool("mobileUI",MOBILE_UI_DEFAULT);
|
mobileUI=e->getConfBool("mobileUI",MOBILE_UI_DEFAULT);
|
||||||
|
edit=e->getConfBool("edit",false);
|
||||||
|
followOrders=e->getConfBool("followOrders",true);
|
||||||
|
followPattern=e->getConfBool("followPattern",true);
|
||||||
|
orderEditMode=e->getConfInt("orderEditMode",0);
|
||||||
|
if (orderEditMode<0) orderEditMode=0;
|
||||||
|
if (orderEditMode>3) orderEditMode=3;
|
||||||
|
|
||||||
syncSettings();
|
syncSettings();
|
||||||
|
|
||||||
|
|
@ -3697,6 +3686,8 @@ bool FurnaceGUI::init() {
|
||||||
dpiScale=settings.dpiScale;
|
dpiScale=settings.dpiScale;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
initSystemPresets();
|
||||||
|
|
||||||
#if !(defined(__APPLE__) || defined(_WIN32))
|
#if !(defined(__APPLE__) || defined(_WIN32))
|
||||||
unsigned char* furIcon=getFurnaceIcon();
|
unsigned char* furIcon=getFurnaceIcon();
|
||||||
SDL_Surface* icon=SDL_CreateRGBSurfaceFrom(furIcon,256,256,32,256*4,0xff,0xff00,0xff0000,0xff000000);
|
SDL_Surface* icon=SDL_CreateRGBSurfaceFrom(furIcon,256,256,32,256*4,0xff,0xff00,0xff0000,0xff000000);
|
||||||
|
|
@ -3873,6 +3864,10 @@ bool FurnaceGUI::finish() {
|
||||||
e->setConf("lockLayout",lockLayout);
|
e->setConf("lockLayout",lockLayout);
|
||||||
e->setConf("fullScreen",fullScreen);
|
e->setConf("fullScreen",fullScreen);
|
||||||
e->setConf("mobileUI",mobileUI);
|
e->setConf("mobileUI",mobileUI);
|
||||||
|
e->setConf("edit",edit);
|
||||||
|
e->setConf("followOrders",followOrders);
|
||||||
|
e->setConf("followPattern",followPattern);
|
||||||
|
e->setConf("orderEditMode",orderEditMode);
|
||||||
|
|
||||||
for (int i=0; i<DIV_MAX_CHANS; i++) {
|
for (int i=0; i<DIV_MAX_CHANS; i++) {
|
||||||
delete oldPat[i];
|
delete oldPat[i];
|
||||||
|
|
@ -4008,6 +4003,7 @@ FurnaceGUI::FurnaceGUI():
|
||||||
chanOscDocked(false),
|
chanOscDocked(false),
|
||||||
*/
|
*/
|
||||||
selecting(false),
|
selecting(false),
|
||||||
|
selectingFull(false),
|
||||||
curNibble(false),
|
curNibble(false),
|
||||||
orderNibble(false),
|
orderNibble(false),
|
||||||
followOrders(true),
|
followOrders(true),
|
||||||
|
|
@ -4167,8 +4163,6 @@ FurnaceGUI::FurnaceGUI():
|
||||||
valueKeys[SDLK_KP_8]=8;
|
valueKeys[SDLK_KP_8]=8;
|
||||||
valueKeys[SDLK_KP_9]=9;
|
valueKeys[SDLK_KP_9]=9;
|
||||||
|
|
||||||
initSystemPresets();
|
|
||||||
|
|
||||||
memset(willExport,1,32*sizeof(bool));
|
memset(willExport,1,32*sizeof(bool));
|
||||||
|
|
||||||
peak[0]=0;
|
peak[0]=0;
|
||||||
|
|
|
||||||
|
|
@ -257,7 +257,10 @@ enum FurnaceGUIFileDialogs {
|
||||||
GUI_FILE_IMPORT_LAYOUT,
|
GUI_FILE_IMPORT_LAYOUT,
|
||||||
GUI_FILE_EXPORT_COLORS,
|
GUI_FILE_EXPORT_COLORS,
|
||||||
GUI_FILE_EXPORT_KEYBINDS,
|
GUI_FILE_EXPORT_KEYBINDS,
|
||||||
GUI_FILE_EXPORT_LAYOUT
|
GUI_FILE_EXPORT_LAYOUT,
|
||||||
|
GUI_FILE_YRW801_ROM_OPEN,
|
||||||
|
GUI_FILE_TG100_ROM_OPEN,
|
||||||
|
GUI_FILE_MU5_ROM_OPEN
|
||||||
};
|
};
|
||||||
|
|
||||||
enum FurnaceGUIWarnings {
|
enum FurnaceGUIWarnings {
|
||||||
|
|
@ -718,11 +721,14 @@ struct FurnaceGUISysDef {
|
||||||
|
|
||||||
struct FurnaceGUISysCategory {
|
struct FurnaceGUISysCategory {
|
||||||
const char* name;
|
const char* name;
|
||||||
|
const char* description;
|
||||||
std::vector<FurnaceGUISysDef> systems;
|
std::vector<FurnaceGUISysDef> systems;
|
||||||
FurnaceGUISysCategory(const char* n):
|
FurnaceGUISysCategory(const char* n, const char* d):
|
||||||
name(n) {}
|
name(n),
|
||||||
|
description(d) {}
|
||||||
FurnaceGUISysCategory():
|
FurnaceGUISysCategory():
|
||||||
name(NULL) {}
|
name(NULL),
|
||||||
|
description(NULL) {}
|
||||||
};
|
};
|
||||||
|
|
||||||
struct FurnaceGUIMacroDesc {
|
struct FurnaceGUIMacroDesc {
|
||||||
|
|
@ -765,7 +771,7 @@ class FurnaceGUI {
|
||||||
bool updateSampleTex;
|
bool updateSampleTex;
|
||||||
|
|
||||||
String workingDir, fileName, clipboard, warnString, errorString, lastError, curFileName, nextFile;
|
String workingDir, fileName, clipboard, warnString, errorString, lastError, curFileName, nextFile;
|
||||||
String workingDirSong, workingDirIns, workingDirWave, workingDirSample, workingDirAudioExport, workingDirVGMExport, workingDirFont, workingDirColors, workingDirKeybinds, workingDirLayout;
|
String workingDirSong, workingDirIns, workingDirWave, workingDirSample, workingDirAudioExport, workingDirVGMExport, workingDirFont, workingDirColors, workingDirKeybinds, workingDirLayout, workingDirROM;
|
||||||
String mmlString[17];
|
String mmlString[17];
|
||||||
String mmlStringW;
|
String mmlStringW;
|
||||||
|
|
||||||
|
|
@ -823,6 +829,9 @@ class FurnaceGUI {
|
||||||
int saaCore;
|
int saaCore;
|
||||||
int nesCore;
|
int nesCore;
|
||||||
int fdsCore;
|
int fdsCore;
|
||||||
|
String yrw801Path;
|
||||||
|
String tg100Path;
|
||||||
|
String mu5Path;
|
||||||
int mainFont;
|
int mainFont;
|
||||||
int patFont;
|
int patFont;
|
||||||
int audioRate;
|
int audioRate;
|
||||||
|
|
@ -861,6 +870,7 @@ class FurnaceGUI {
|
||||||
int roundedButtons;
|
int roundedButtons;
|
||||||
int roundedMenus;
|
int roundedMenus;
|
||||||
int loadJapanese;
|
int loadJapanese;
|
||||||
|
int loadChinese;
|
||||||
int fmLayout;
|
int fmLayout;
|
||||||
int sampleLayout;
|
int sampleLayout;
|
||||||
int waveLayout;
|
int waveLayout;
|
||||||
|
|
@ -890,6 +900,7 @@ class FurnaceGUI {
|
||||||
int hiddenSystems;
|
int hiddenSystems;
|
||||||
int horizontalDataView;
|
int horizontalDataView;
|
||||||
int noMultiSystem;
|
int noMultiSystem;
|
||||||
|
int oldMacroVSlider;
|
||||||
unsigned int maxUndoSteps;
|
unsigned int maxUndoSteps;
|
||||||
String mainFontPath;
|
String mainFontPath;
|
||||||
String patFontPath;
|
String patFontPath;
|
||||||
|
|
@ -909,6 +920,9 @@ class FurnaceGUI {
|
||||||
saaCore(1),
|
saaCore(1),
|
||||||
nesCore(0),
|
nesCore(0),
|
||||||
fdsCore(0),
|
fdsCore(0),
|
||||||
|
yrw801Path(""),
|
||||||
|
tg100Path(""),
|
||||||
|
mu5Path(""),
|
||||||
mainFont(0),
|
mainFont(0),
|
||||||
patFont(0),
|
patFont(0),
|
||||||
audioRate(44100),
|
audioRate(44100),
|
||||||
|
|
@ -945,6 +959,7 @@ class FurnaceGUI {
|
||||||
roundedButtons(1),
|
roundedButtons(1),
|
||||||
roundedMenus(0),
|
roundedMenus(0),
|
||||||
loadJapanese(0),
|
loadJapanese(0),
|
||||||
|
loadChinese(0),
|
||||||
fmLayout(0),
|
fmLayout(0),
|
||||||
sampleLayout(0),
|
sampleLayout(0),
|
||||||
waveLayout(0),
|
waveLayout(0),
|
||||||
|
|
@ -974,6 +989,7 @@ class FurnaceGUI {
|
||||||
hiddenSystems(0),
|
hiddenSystems(0),
|
||||||
horizontalDataView(0),
|
horizontalDataView(0),
|
||||||
noMultiSystem(0),
|
noMultiSystem(0),
|
||||||
|
oldMacroVSlider(0),
|
||||||
maxUndoSteps(100),
|
maxUndoSteps(100),
|
||||||
mainFontPath(""),
|
mainFontPath(""),
|
||||||
patFontPath(""),
|
patFontPath(""),
|
||||||
|
|
@ -1003,7 +1019,7 @@ class FurnaceGUI {
|
||||||
*/
|
*/
|
||||||
|
|
||||||
SelectionPoint selStart, selEnd, cursor;
|
SelectionPoint selStart, selEnd, cursor;
|
||||||
bool selecting, curNibble, orderNibble, followOrders, followPattern, changeAllOrders, mobileUI;
|
bool selecting, selectingFull, curNibble, orderNibble, followOrders, followPattern, changeAllOrders, mobileUI;
|
||||||
bool collapseWindow, demandScrollX, fancyPattern, wantPatName, firstFrame, tempoView, waveHex, lockLayout, editOptsVisible, latchNibble, nonLatchNibble;
|
bool collapseWindow, demandScrollX, fancyPattern, wantPatName, firstFrame, tempoView, waveHex, lockLayout, editOptsVisible, latchNibble, nonLatchNibble;
|
||||||
FurnaceGUIWindows curWindow, nextWindow, curWindowLast;
|
FurnaceGUIWindows curWindow, nextWindow, curWindowLast;
|
||||||
float peak[2];
|
float peak[2];
|
||||||
|
|
@ -1108,7 +1124,7 @@ class FurnaceGUI {
|
||||||
ImVec2 patWindowPos, patWindowSize;
|
ImVec2 patWindowPos, patWindowSize;
|
||||||
|
|
||||||
// pattern view specific
|
// pattern view specific
|
||||||
ImVec2 threeChars, twoChars;
|
ImVec2 fourChars, threeChars, twoChars;
|
||||||
SelectionPoint sel1, sel2;
|
SelectionPoint sel1, sel2;
|
||||||
int dummyRows, demandX;
|
int dummyRows, demandX;
|
||||||
int transposeAmount, randomizeMin, randomizeMax, fadeMin, fadeMax;
|
int transposeAmount, randomizeMin, randomizeMax, fadeMin, fadeMax;
|
||||||
|
|
@ -1249,8 +1265,8 @@ class FurnaceGUI {
|
||||||
void commitSettings();
|
void commitSettings();
|
||||||
void processDrags(int dragX, int dragY);
|
void processDrags(int dragX, int dragY);
|
||||||
|
|
||||||
void startSelection(int xCoarse, int xFine, int y);
|
void startSelection(int xCoarse, int xFine, int y, bool fullRow=false);
|
||||||
void updateSelection(int xCoarse, int xFine, int y);
|
void updateSelection(int xCoarse, int xFine, int y, bool fullRow=false);
|
||||||
void finishSelection();
|
void finishSelection();
|
||||||
|
|
||||||
void moveCursor(int x, int y, bool select);
|
void moveCursor(int x, int y, bool select);
|
||||||
|
|
@ -1307,8 +1323,6 @@ class FurnaceGUI {
|
||||||
void initSystemPresets();
|
void initSystemPresets();
|
||||||
|
|
||||||
void encodeMMLStr(String& target, int* macro, int macroLen, int macroLoop, int macroRel, bool hex=false);
|
void encodeMMLStr(String& target, int* macro, int macroLen, int macroLoop, int macroRel, bool hex=false);
|
||||||
void encodeMMLStr(String& target, unsigned char* macro, unsigned char macroLen, signed char macroLoop, signed char macroRel);
|
|
||||||
void decodeMMLStr(String& source, unsigned char* macro, unsigned char& macroLen, signed char& macroLoop, int macroMin, int macroMax, signed char& macroRel);
|
|
||||||
void decodeMMLStr(String& source, int* macro, unsigned char& macroLen, signed char& macroLoop, int macroMin, int macroMax, signed char& macroRel);
|
void decodeMMLStr(String& source, int* macro, unsigned char& macroLen, signed char& macroLoop, int macroMin, int macroMax, signed char& macroRel);
|
||||||
void decodeMMLStrW(String& source, int* macro, int& macroLen, int macroMax, bool hex=false);
|
void decodeMMLStrW(String& source, int* macro, int& macroLen, int macroMax, bool hex=false);
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -101,7 +101,7 @@ const char* insTypes[DIV_INS_MAX]={
|
||||||
"Konami SCC/Bubble System WSG",
|
"Konami SCC/Bubble System WSG",
|
||||||
"FM (OPZ)",
|
"FM (OPZ)",
|
||||||
"POKEY",
|
"POKEY",
|
||||||
"PC Beeper",
|
"Beeper",
|
||||||
"WonderSwan",
|
"WonderSwan",
|
||||||
"Atari Lynx",
|
"Atari Lynx",
|
||||||
"VERA",
|
"VERA",
|
||||||
|
|
@ -831,16 +831,21 @@ const int availableSystems[]={
|
||||||
DIV_SYSTEM_AY8910,
|
DIV_SYSTEM_AY8910,
|
||||||
DIV_SYSTEM_AMIGA,
|
DIV_SYSTEM_AMIGA,
|
||||||
DIV_SYSTEM_PCSPKR,
|
DIV_SYSTEM_PCSPKR,
|
||||||
|
DIV_SYSTEM_SFX_BEEPER,
|
||||||
DIV_SYSTEM_YMU759,
|
DIV_SYSTEM_YMU759,
|
||||||
DIV_SYSTEM_DUMMY,
|
DIV_SYSTEM_DUMMY,
|
||||||
DIV_SYSTEM_SOUND_UNIT,
|
DIV_SYSTEM_SOUND_UNIT,
|
||||||
DIV_SYSTEM_OPN,
|
DIV_SYSTEM_OPN,
|
||||||
|
DIV_SYSTEM_OPN_EXT,
|
||||||
DIV_SYSTEM_PC98,
|
DIV_SYSTEM_PC98,
|
||||||
|
DIV_SYSTEM_PC98_EXT,
|
||||||
DIV_SYSTEM_OPLL,
|
DIV_SYSTEM_OPLL,
|
||||||
DIV_SYSTEM_OPLL_DRUMS,
|
DIV_SYSTEM_OPLL_DRUMS,
|
||||||
DIV_SYSTEM_VRC7,
|
DIV_SYSTEM_VRC7,
|
||||||
DIV_SYSTEM_OPL,
|
DIV_SYSTEM_OPL,
|
||||||
DIV_SYSTEM_OPL_DRUMS,
|
DIV_SYSTEM_OPL_DRUMS,
|
||||||
|
DIV_SYSTEM_Y8950,
|
||||||
|
DIV_SYSTEM_Y8950_DRUMS,
|
||||||
DIV_SYSTEM_OPL2,
|
DIV_SYSTEM_OPL2,
|
||||||
DIV_SYSTEM_OPL2_DRUMS,
|
DIV_SYSTEM_OPL2_DRUMS,
|
||||||
DIV_SYSTEM_OPL3,
|
DIV_SYSTEM_OPL3,
|
||||||
|
|
|
||||||
|
|
@ -1077,7 +1077,7 @@ void FurnaceGUI::drawMacros(std::vector<FurnaceGUIMacroDesc>& macros) {
|
||||||
float loopIndicator[256];
|
float loopIndicator[256];
|
||||||
int index=0;
|
int index=0;
|
||||||
|
|
||||||
float reservedSpace=ImGui::GetStyle().ScrollbarSize;
|
float reservedSpace=(settings.oldMacroVSlider)?(20.0f*dpiScale+ImGui::GetStyle().ItemSpacing.x):ImGui::GetStyle().ScrollbarSize;
|
||||||
|
|
||||||
if (ImGui::BeginTable("MacroSpace",2)) {
|
if (ImGui::BeginTable("MacroSpace",2)) {
|
||||||
ImGui::TableSetupColumn("c0",ImGuiTableColumnFlags_WidthFixed,0.0);
|
ImGui::TableSetupColumn("c0",ImGuiTableColumnFlags_WidthFixed,0.0);
|
||||||
|
|
@ -1152,8 +1152,8 @@ void FurnaceGUI::drawMacros(std::vector<FurnaceGUIMacroDesc>& macros) {
|
||||||
i.macro->vZoom=24;
|
i.macro->vZoom=24;
|
||||||
i.macro->vScroll=120-12;
|
i.macro->vScroll=120-12;
|
||||||
} else if (i.macro->name=="pitch") {
|
} else if (i.macro->name=="pitch") {
|
||||||
i.macro->vZoom=64;
|
i.macro->vZoom=128;
|
||||||
i.macro->vScroll=1024-32;
|
i.macro->vScroll=2048-64;
|
||||||
} else {
|
} else {
|
||||||
i.macro->vZoom=i.max-i.min;
|
i.macro->vZoom=i.max-i.min;
|
||||||
i.macro->vScroll=0;
|
i.macro->vScroll=0;
|
||||||
|
|
@ -1192,37 +1192,60 @@ void FurnaceGUI::drawMacros(std::vector<FurnaceGUIMacroDesc>& macros) {
|
||||||
processDrags(ImGui::GetMousePos().x,ImGui::GetMousePos().y);
|
processDrags(ImGui::GetMousePos().x,ImGui::GetMousePos().y);
|
||||||
}
|
}
|
||||||
if (i.macro->open) {
|
if (i.macro->open) {
|
||||||
if (ImGui::IsItemHovered() && ctrlWheeling) {
|
if (ImGui::IsItemHovered()) {
|
||||||
if (ImGui::IsKeyDown(ImGuiKey_LeftShift) || ImGui::IsKeyDown(ImGuiKey_RightShift)) {
|
if (ctrlWheeling) {
|
||||||
i.macro->vZoom+=wheelY;
|
if (ImGui::IsKeyDown(ImGuiKey_LeftShift) || ImGui::IsKeyDown(ImGuiKey_RightShift)) {
|
||||||
if (i.macro->vZoom<1) i.macro->vZoom=1;
|
i.macro->vZoom+=wheelY*(1+(i.macro->vZoom>>4));
|
||||||
if (i.macro->vZoom>(i.max-i.min)) i.macro->vZoom=i.max-i.min;
|
if (i.macro->vZoom<1) i.macro->vZoom=1;
|
||||||
if ((i.macro->vScroll+i.macro->vZoom)>(i.max-i.min)) {
|
if (i.macro->vZoom>(i.max-i.min)) i.macro->vZoom=i.max-i.min;
|
||||||
i.macro->vScroll=(i.max-i.min)-i.macro->vZoom;
|
if ((i.macro->vScroll+i.macro->vZoom)>(i.max-i.min)) {
|
||||||
|
i.macro->vScroll=(i.max-i.min)-i.macro->vZoom;
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
macroPointSize+=wheelY;
|
||||||
|
if (macroPointSize<1) macroPointSize=1;
|
||||||
|
if (macroPointSize>256) macroPointSize=256;
|
||||||
}
|
}
|
||||||
} else {
|
} else if ((ImGui::IsKeyDown(ImGuiKey_LeftShift) || ImGui::IsKeyDown(ImGuiKey_RightShift)) && wheelY!=0) {
|
||||||
macroPointSize+=wheelY;
|
i.macro->vScroll+=wheelY*(1+(i.macro->vZoom>>4));
|
||||||
if (macroPointSize<1) macroPointSize=1;
|
if (i.macro->vScroll<0) i.macro->vScroll=0;
|
||||||
if (macroPointSize>256) macroPointSize=256;
|
if (i.macro->vScroll>((i.max-i.min)-i.macro->vZoom)) i.macro->vScroll=(i.max-i.min)-i.macro->vZoom;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// slider
|
// slider
|
||||||
if (!i.isBitfield) {
|
if (!i.isBitfield) {
|
||||||
ImS64 scrollV=(i.max-i.min-i.macro->vZoom)-i.macro->vScroll;
|
if (settings.oldMacroVSlider) {
|
||||||
ImS64 availV=i.macro->vZoom;
|
ImGui::SameLine(0.0f);
|
||||||
ImS64 contentsV=(i.max-i.min);
|
if (ImGui::VSliderInt("IMacroVScroll",ImVec2(20.0f*dpiScale,i.height*dpiScale),&i.macro->vScroll,0,(i.max-i.min)-i.macro->vZoom,"")) {
|
||||||
|
if (i.macro->vScroll<0) i.macro->vScroll=0;
|
||||||
|
if (i.macro->vScroll>((i.max-i.min)-i.macro->vZoom)) i.macro->vScroll=(i.max-i.min)-i.macro->vZoom;
|
||||||
|
}
|
||||||
|
if (ImGui::IsItemHovered() && ctrlWheeling) {
|
||||||
|
i.macro->vScroll+=wheelY*(1+(i.macro->vZoom>>4));
|
||||||
|
if (i.macro->vScroll<0) i.macro->vScroll=0;
|
||||||
|
if (i.macro->vScroll>((i.max-i.min)-i.macro->vZoom)) i.macro->vScroll=(i.max-i.min)-i.macro->vZoom;
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
ImS64 scrollV=(i.max-i.min-i.macro->vZoom)-i.macro->vScroll;
|
||||||
|
ImS64 availV=i.macro->vZoom;
|
||||||
|
ImS64 contentsV=(i.max-i.min);
|
||||||
|
|
||||||
ImGui::SameLine(0.0f);
|
ImGui::SameLine(0.0f);
|
||||||
ImRect scrollbarPos=ImRect(ImGui::GetCursorScreenPos(),ImGui::GetCursorScreenPos());
|
ImGui::SetCursorPosX(ImGui::GetCursorPosX()-ImGui::GetStyle().ItemSpacing.x);
|
||||||
scrollbarPos.Min.x-=ImGui::GetStyle().ItemSpacing.x;
|
ImRect scrollbarPos=ImRect(ImGui::GetCursorScreenPos(),ImGui::GetCursorScreenPos());
|
||||||
scrollbarPos.Max.x+=ImGui::GetStyle().ScrollbarSize;
|
scrollbarPos.Max.x+=ImGui::GetStyle().ScrollbarSize;
|
||||||
scrollbarPos.Max.x-=ImGui::GetStyle().ItemSpacing.x;
|
scrollbarPos.Max.y+=i.height*dpiScale;
|
||||||
scrollbarPos.Max.y+=i.height*dpiScale;
|
ImGui::Dummy(ImVec2(ImGui::GetStyle().ScrollbarSize,i.height*dpiScale));
|
||||||
ImGui::Dummy(ImVec2(ImGui::GetStyle().ScrollbarSize,i.height*dpiScale));
|
if (ImGui::IsItemHovered() && ctrlWheeling) {
|
||||||
|
i.macro->vScroll+=wheelY*(1+(i.macro->vZoom>>4));
|
||||||
|
if (i.macro->vScroll<0) i.macro->vScroll=0;
|
||||||
|
if (i.macro->vScroll>((i.max-i.min)-i.macro->vZoom)) i.macro->vScroll=(i.max-i.min)-i.macro->vZoom;
|
||||||
|
}
|
||||||
|
|
||||||
if (ImGui::ScrollbarEx(scrollbarPos,ImGui::GetID("IMacroVScroll"),ImGuiAxis_Y,&scrollV,availV,contentsV,0)) {
|
if (ImGui::ScrollbarEx(scrollbarPos,ImGui::GetID("IMacroVScroll"),ImGuiAxis_Y,&scrollV,availV,contentsV,0)) {
|
||||||
i.macro->vScroll=(i.max-i.min-i.macro->vZoom)-scrollV;
|
i.macro->vScroll=(i.max-i.min-i.macro->vZoom)-scrollV;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -2851,7 +2874,7 @@ void FurnaceGUI::drawInsEdit() {
|
||||||
if (ins->type==DIV_INS_GB) {
|
if (ins->type==DIV_INS_GB) {
|
||||||
volMax=0;
|
volMax=0;
|
||||||
}
|
}
|
||||||
if (ins->type==DIV_INS_PET) {
|
if (ins->type==DIV_INS_PET || ins->type==DIV_INS_BEEPER) {
|
||||||
volMax=1;
|
volMax=1;
|
||||||
}
|
}
|
||||||
if (ins->type==DIV_INS_FDS) {
|
if (ins->type==DIV_INS_FDS) {
|
||||||
|
|
@ -2883,6 +2906,10 @@ void FurnaceGUI::drawInsEdit() {
|
||||||
dutyLabel="Duty/Int";
|
dutyLabel="Duty/Int";
|
||||||
dutyMax=10;
|
dutyMax=10;
|
||||||
}
|
}
|
||||||
|
if (ins->type==DIV_INS_BEEPER) {
|
||||||
|
dutyLabel="Pulse Width";
|
||||||
|
dutyMax=255;
|
||||||
|
}
|
||||||
if (ins->type==DIV_INS_AY8930) {
|
if (ins->type==DIV_INS_AY8930) {
|
||||||
dutyMax=255;
|
dutyMax=255;
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -18,6 +18,7 @@
|
||||||
*/
|
*/
|
||||||
|
|
||||||
#include "gui.h"
|
#include "gui.h"
|
||||||
|
#include <imgui.h>
|
||||||
|
|
||||||
void FurnaceGUI::drawNewSong() {
|
void FurnaceGUI::drawNewSong() {
|
||||||
bool accepted=false;
|
bool accepted=false;
|
||||||
|
|
@ -27,44 +28,53 @@ void FurnaceGUI::drawNewSong() {
|
||||||
ImGui::Text("Choose a System!");
|
ImGui::Text("Choose a System!");
|
||||||
ImGui::PopFont();
|
ImGui::PopFont();
|
||||||
|
|
||||||
if (ImGui::BeginTable("sysPicker",2)) {
|
ImVec2 avail=ImGui::GetContentRegionAvail();
|
||||||
ImGui::TableSetupColumn("c0",ImGuiTableColumnFlags_WidthFixed,0.0f);
|
avail.y-=ImGui::GetFrameHeightWithSpacing();
|
||||||
ImGui::TableSetupColumn("c1",ImGuiTableColumnFlags_WidthStretch,0.0f);
|
|
||||||
|
|
||||||
ImGui::TableNextRow(ImGuiTableRowFlags_Headers);
|
if (ImGui::BeginChild("sysPickerC",avail,false,ImGuiWindowFlags_NoScrollWithMouse|ImGuiWindowFlags_NoScrollbar)) {
|
||||||
ImGui::TableNextColumn();
|
if (ImGui::BeginTable("sysPicker",2,ImGuiTableFlags_BordersInnerV)) {
|
||||||
ImGui::Text("Categories");
|
ImGui::TableSetupColumn("c0",ImGuiTableColumnFlags_WidthFixed,0.0f);
|
||||||
ImGui::TableNextColumn();
|
ImGui::TableSetupColumn("c1",ImGuiTableColumnFlags_WidthStretch,0.0f);
|
||||||
ImGui::Text("Systems");
|
|
||||||
|
|
||||||
ImGui::TableNextRow();
|
ImGui::TableNextRow(ImGuiTableRowFlags_Headers);
|
||||||
|
ImGui::TableNextColumn();
|
||||||
|
ImGui::Text("Categories");
|
||||||
|
ImGui::TableNextColumn();
|
||||||
|
ImGui::Text("Systems");
|
||||||
|
|
||||||
// CATEGORIES
|
ImGui::TableNextRow();
|
||||||
ImGui::TableNextColumn();
|
|
||||||
int index=0;
|
|
||||||
for (FurnaceGUISysCategory& i: sysCategories) {
|
|
||||||
if (ImGui::Selectable(i.name,newSongCategory==index,ImGuiSelectableFlags_DontClosePopups)) { \
|
|
||||||
newSongCategory=index;
|
|
||||||
}
|
|
||||||
index++;
|
|
||||||
}
|
|
||||||
|
|
||||||
// SYSTEMS
|
// CATEGORIES
|
||||||
ImGui::TableNextColumn();
|
ImGui::TableNextColumn();
|
||||||
if (ImGui::BeginTable("Systems",1,ImGuiTableFlags_BordersInnerV|ImGuiTableFlags_ScrollY)) {
|
int index=0;
|
||||||
for (FurnaceGUISysDef& i: sysCategories[newSongCategory].systems) {
|
for (FurnaceGUISysCategory& i: sysCategories) {
|
||||||
ImGui::TableNextRow();
|
if (ImGui::Selectable(i.name,newSongCategory==index,ImGuiSelectableFlags_DontClosePopups)) { \
|
||||||
ImGui::TableNextColumn();
|
newSongCategory=index;
|
||||||
if (ImGui::Selectable(i.name,false,ImGuiSelectableFlags_DontClosePopups)) {
|
|
||||||
nextDesc=i.definition.data();
|
|
||||||
accepted=true;
|
|
||||||
}
|
}
|
||||||
|
if (ImGui::IsItemHovered()) {
|
||||||
|
ImGui::SetTooltip("%s",i.description);
|
||||||
|
}
|
||||||
|
index++;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// SYSTEMS
|
||||||
|
ImGui::TableNextColumn();
|
||||||
|
if (ImGui::BeginTable("Systems",1,ImGuiTableFlags_BordersInnerV|ImGuiTableFlags_ScrollY)) {
|
||||||
|
for (FurnaceGUISysDef& i: sysCategories[newSongCategory].systems) {
|
||||||
|
ImGui::TableNextRow();
|
||||||
|
ImGui::TableNextColumn();
|
||||||
|
if (ImGui::Selectable(i.name,false,ImGuiSelectableFlags_DontClosePopups)) {
|
||||||
|
nextDesc=i.definition.data();
|
||||||
|
accepted=true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
ImGui::EndTable();
|
||||||
|
}
|
||||||
|
|
||||||
ImGui::EndTable();
|
ImGui::EndTable();
|
||||||
}
|
}
|
||||||
|
|
||||||
ImGui::EndTable();
|
|
||||||
}
|
}
|
||||||
|
ImGui::EndChild();
|
||||||
|
|
||||||
if (ImGui::Button("I'm feeling lucky")) {
|
if (ImGui::Button("I'm feeling lucky")) {
|
||||||
if (sysCategories.size()==0) {
|
if (sysCategories.size()==0) {
|
||||||
|
|
|
||||||
|
|
@ -88,11 +88,21 @@ inline void FurnaceGUI::patternRow(int i, bool isPlaying, float lineHeight, int
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
// row number
|
// row number
|
||||||
|
ImGui::PushStyleColor(ImGuiCol_Text,rowIndexColor);
|
||||||
|
|
||||||
if (settings.patRowsBase==1) {
|
if (settings.patRowsBase==1) {
|
||||||
ImGui::TextColored(rowIndexColor," %.2X ",i);
|
snprintf(id,31," %.2X ##PR_%d",i,i);
|
||||||
} else {
|
} else {
|
||||||
ImGui::TextColored(rowIndexColor,"%3d ",i);
|
snprintf(id,31,"%3d ##PR_%d",i,i);
|
||||||
}
|
}
|
||||||
|
ImGui::Selectable(id,false,ImGuiSelectableFlags_NoPadWithHalfSpacing,fourChars);
|
||||||
|
if (ImGui::IsItemHovered(ImGuiHoveredFlags_AllowWhenBlockedByActiveItem)) {
|
||||||
|
updateSelection(0,0,i,true);
|
||||||
|
}
|
||||||
|
if (ImGui::IsItemClicked()) {
|
||||||
|
startSelection(0,0,i,true);
|
||||||
|
}
|
||||||
|
ImGui::PopStyleColor();
|
||||||
// for each column
|
// for each column
|
||||||
for (int j=0; j<chans; j++) {
|
for (int j=0; j<chans; j++) {
|
||||||
// check if channel is not hidden
|
// check if channel is not hidden
|
||||||
|
|
@ -535,6 +545,7 @@ void FurnaceGUI::drawPattern() {
|
||||||
ImGui::TextColored(uiColors[GUI_COLOR_EE_VALUE]," %.2X",e->getExtValue());
|
ImGui::TextColored(uiColors[GUI_COLOR_EE_VALUE]," %.2X",e->getExtValue());
|
||||||
}
|
}
|
||||||
float oneCharSize=ImGui::CalcTextSize("A").x;
|
float oneCharSize=ImGui::CalcTextSize("A").x;
|
||||||
|
fourChars=ImVec2(oneCharSize*4.0f,lineHeight);
|
||||||
threeChars=ImVec2(oneCharSize*3.0f,lineHeight);
|
threeChars=ImVec2(oneCharSize*3.0f,lineHeight);
|
||||||
twoChars=ImVec2(oneCharSize*2.0f,lineHeight);
|
twoChars=ImVec2(oneCharSize*2.0f,lineHeight);
|
||||||
//ImVec2 oneChar=ImVec2(oneCharSize,lineHeight);
|
//ImVec2 oneChar=ImVec2(oneCharSize,lineHeight);
|
||||||
|
|
|
||||||
|
|
@ -31,27 +31,41 @@
|
||||||
// ));
|
// ));
|
||||||
|
|
||||||
void FurnaceGUI::initSystemPresets() {
|
void FurnaceGUI::initSystemPresets() {
|
||||||
|
sysCategories.clear();
|
||||||
|
|
||||||
FurnaceGUISysCategory cat;
|
FurnaceGUISysCategory cat;
|
||||||
|
|
||||||
cat=FurnaceGUISysCategory("FM");
|
cat=FurnaceGUISysCategory("FM","chips which use frequency modulation (FM) to generate sound.\nsome of these also pack more (like square and sample channels).");
|
||||||
cat.systems.push_back(FurnaceGUISysDef(
|
|
||||||
"Yamaha YM2612", {
|
|
||||||
DIV_SYSTEM_YM2612, 64, 0, 0,
|
|
||||||
0
|
|
||||||
}
|
|
||||||
));
|
|
||||||
cat.systems.push_back(FurnaceGUISysDef(
|
|
||||||
"Yamaha YM2612 (extended channel 3)", {
|
|
||||||
DIV_SYSTEM_YM2612_EXT, 64, 0, 0,
|
|
||||||
0
|
|
||||||
}
|
|
||||||
));
|
|
||||||
cat.systems.push_back(FurnaceGUISysDef(
|
cat.systems.push_back(FurnaceGUISysDef(
|
||||||
"Yamaha YM2151", {
|
"Yamaha YM2151", {
|
||||||
DIV_SYSTEM_YM2151, 64, 0, 0,
|
DIV_SYSTEM_YM2151, 64, 0, 0,
|
||||||
0
|
0
|
||||||
}
|
}
|
||||||
));
|
));
|
||||||
|
cat.systems.push_back(FurnaceGUISysDef(
|
||||||
|
"Yamaha YM2203", {
|
||||||
|
DIV_SYSTEM_OPN, 64, 0, 3,
|
||||||
|
0
|
||||||
|
}
|
||||||
|
));
|
||||||
|
cat.systems.push_back(FurnaceGUISysDef(
|
||||||
|
"Yamaha YM2203 (extended channel 3)", {
|
||||||
|
DIV_SYSTEM_OPN_EXT, 64, 0, 3,
|
||||||
|
0
|
||||||
|
}
|
||||||
|
));
|
||||||
|
cat.systems.push_back(FurnaceGUISysDef(
|
||||||
|
"Yamaha YM2608", {
|
||||||
|
DIV_SYSTEM_PC98, 64, 0, 3,
|
||||||
|
0
|
||||||
|
}
|
||||||
|
));
|
||||||
|
cat.systems.push_back(FurnaceGUISysDef(
|
||||||
|
"Yamaha YM2608 (extended channel 3)", {
|
||||||
|
DIV_SYSTEM_PC98_EXT, 64, 0, 3,
|
||||||
|
0
|
||||||
|
}
|
||||||
|
));
|
||||||
cat.systems.push_back(FurnaceGUISysDef(
|
cat.systems.push_back(FurnaceGUISysDef(
|
||||||
"Yamaha YM2610", {
|
"Yamaha YM2610", {
|
||||||
DIV_SYSTEM_YM2610_FULL, 64, 0, 0,
|
DIV_SYSTEM_YM2610_FULL, 64, 0, 0,
|
||||||
|
|
@ -76,6 +90,18 @@ void FurnaceGUI::initSystemPresets() {
|
||||||
0
|
0
|
||||||
}
|
}
|
||||||
));
|
));
|
||||||
|
cat.systems.push_back(FurnaceGUISysDef(
|
||||||
|
"Yamaha YM2612", {
|
||||||
|
DIV_SYSTEM_YM2612, 64, 0, (int)0x80000000,
|
||||||
|
0
|
||||||
|
}
|
||||||
|
));
|
||||||
|
cat.systems.push_back(FurnaceGUISysDef(
|
||||||
|
"Yamaha YM2612 (extended channel 3)", {
|
||||||
|
DIV_SYSTEM_YM2612_EXT, 64, 0, (int)0x80000000,
|
||||||
|
0
|
||||||
|
}
|
||||||
|
));
|
||||||
cat.systems.push_back(FurnaceGUISysDef(
|
cat.systems.push_back(FurnaceGUISysDef(
|
||||||
"Yamaha YM2413", {
|
"Yamaha YM2413", {
|
||||||
DIV_SYSTEM_OPLL, 64, 0, 0,
|
DIV_SYSTEM_OPLL, 64, 0, 0,
|
||||||
|
|
@ -94,6 +120,18 @@ void FurnaceGUI::initSystemPresets() {
|
||||||
0
|
0
|
||||||
}
|
}
|
||||||
));
|
));
|
||||||
|
cat.systems.push_back(FurnaceGUISysDef(
|
||||||
|
"Yamaha YM3438", {
|
||||||
|
DIV_SYSTEM_YM2612, 64, 0, 0,
|
||||||
|
0
|
||||||
|
}
|
||||||
|
));
|
||||||
|
cat.systems.push_back(FurnaceGUISysDef(
|
||||||
|
"Yamaha YM3438 (extended channel 3)", {
|
||||||
|
DIV_SYSTEM_YM2612_EXT, 64, 0, 0,
|
||||||
|
0
|
||||||
|
}
|
||||||
|
));
|
||||||
cat.systems.push_back(FurnaceGUISysDef(
|
cat.systems.push_back(FurnaceGUISysDef(
|
||||||
"Yamaha YM3526", {
|
"Yamaha YM3526", {
|
||||||
DIV_SYSTEM_OPL, 64, 0, 0,
|
DIV_SYSTEM_OPL, 64, 0, 0,
|
||||||
|
|
@ -106,6 +144,18 @@ void FurnaceGUI::initSystemPresets() {
|
||||||
0
|
0
|
||||||
}
|
}
|
||||||
));
|
));
|
||||||
|
cat.systems.push_back(FurnaceGUISysDef(
|
||||||
|
"Yamaha Y8950", {
|
||||||
|
DIV_SYSTEM_Y8950, 64, 0, 0,
|
||||||
|
0
|
||||||
|
}
|
||||||
|
));
|
||||||
|
cat.systems.push_back(FurnaceGUISysDef(
|
||||||
|
"Yamaha Y8950 (drums mode)", {
|
||||||
|
DIV_SYSTEM_Y8950_DRUMS, 64, 0, 0,
|
||||||
|
0
|
||||||
|
}
|
||||||
|
));
|
||||||
cat.systems.push_back(FurnaceGUISysDef(
|
cat.systems.push_back(FurnaceGUISysDef(
|
||||||
"Yamaha YM3812", {
|
"Yamaha YM3812", {
|
||||||
DIV_SYSTEM_OPL2, 64, 0, 0,
|
DIV_SYSTEM_OPL2, 64, 0, 0,
|
||||||
|
|
@ -130,11 +180,25 @@ void FurnaceGUI::initSystemPresets() {
|
||||||
0
|
0
|
||||||
}
|
}
|
||||||
));
|
));
|
||||||
|
if (settings.hiddenSystems) {
|
||||||
|
cat.systems.push_back(FurnaceGUISysDef(
|
||||||
|
"Yamaha YMU759", {
|
||||||
|
DIV_SYSTEM_YMU759, 64, 0, 0,
|
||||||
|
0
|
||||||
|
}
|
||||||
|
));
|
||||||
|
}
|
||||||
sysCategories.push_back(cat);
|
sysCategories.push_back(cat);
|
||||||
|
|
||||||
cat=FurnaceGUISysCategory("Square");
|
cat=FurnaceGUISysCategory("Square","these chips generate square/pulse tones only (but may include noise).");
|
||||||
cat.systems.push_back(FurnaceGUISysDef(
|
cat.systems.push_back(FurnaceGUISysDef(
|
||||||
"TI SN76489", {
|
"TI SN76489", {
|
||||||
|
DIV_SYSTEM_SMS, 64, 0, 4,
|
||||||
|
0
|
||||||
|
}
|
||||||
|
));
|
||||||
|
cat.systems.push_back(FurnaceGUISysDef(
|
||||||
|
"Sega PSG (SN76489-like)", {
|
||||||
DIV_SYSTEM_SMS, 64, 0, 0,
|
DIV_SYSTEM_SMS, 64, 0, 0,
|
||||||
0
|
0
|
||||||
}
|
}
|
||||||
|
|
@ -145,15 +209,33 @@ void FurnaceGUI::initSystemPresets() {
|
||||||
0
|
0
|
||||||
}
|
}
|
||||||
));
|
));
|
||||||
|
cat.systems.push_back(FurnaceGUISysDef(
|
||||||
|
"Yamaha YM2149(F)", {
|
||||||
|
DIV_SYSTEM_AY8910, 64, 0, 16,
|
||||||
|
0
|
||||||
|
}
|
||||||
|
));
|
||||||
cat.systems.push_back(FurnaceGUISysDef(
|
cat.systems.push_back(FurnaceGUISysDef(
|
||||||
"Philips SAA1099", {
|
"Philips SAA1099", {
|
||||||
DIV_SYSTEM_SAA1099, 64, 0, 0,
|
DIV_SYSTEM_SAA1099, 64, 0, 0,
|
||||||
0
|
0
|
||||||
}
|
}
|
||||||
));
|
));
|
||||||
|
cat.systems.push_back(FurnaceGUISysDef(
|
||||||
|
"PC Speaker", {
|
||||||
|
DIV_SYSTEM_PCSPKR, 32, 0, 0,
|
||||||
|
0
|
||||||
|
}
|
||||||
|
));
|
||||||
|
cat.systems.push_back(FurnaceGUISysDef(
|
||||||
|
"Commodore VIC", {
|
||||||
|
DIV_SYSTEM_VIC20, 64, 0, 1,
|
||||||
|
0
|
||||||
|
}
|
||||||
|
));
|
||||||
sysCategories.push_back(cat);
|
sysCategories.push_back(cat);
|
||||||
|
|
||||||
cat=FurnaceGUISysCategory("Sample");
|
cat=FurnaceGUISysCategory("Sample","chips/systems which use PCM or ADPCM samples for sound synthesis.");
|
||||||
cat.systems.push_back(FurnaceGUISysDef(
|
cat.systems.push_back(FurnaceGUISysDef(
|
||||||
"Amiga", {
|
"Amiga", {
|
||||||
DIV_SYSTEM_AMIGA, 64, 0, 0,
|
DIV_SYSTEM_AMIGA, 64, 0, 0,
|
||||||
|
|
@ -180,7 +262,129 @@ void FurnaceGUI::initSystemPresets() {
|
||||||
));
|
));
|
||||||
sysCategories.push_back(cat);
|
sysCategories.push_back(cat);
|
||||||
|
|
||||||
cat=FurnaceGUISysCategory("Game consoles");
|
cat=FurnaceGUISysCategory("Wavetable","chips which use user-specified waveforms to generate sound.");
|
||||||
|
cat.systems.push_back(FurnaceGUISysDef(
|
||||||
|
"PC Engine", {
|
||||||
|
DIV_SYSTEM_PCE, 64, 0, 0,
|
||||||
|
0
|
||||||
|
}
|
||||||
|
));
|
||||||
|
cat.systems.push_back(FurnaceGUISysDef(
|
||||||
|
"Commodore PET (pseudo-wavetable)", {
|
||||||
|
DIV_SYSTEM_PET, 64, 0, 0,
|
||||||
|
0
|
||||||
|
}
|
||||||
|
));
|
||||||
|
cat.systems.push_back(FurnaceGUISysDef(
|
||||||
|
"Konami Bubble System WSG", {
|
||||||
|
DIV_SYSTEM_BUBSYS_WSG, 64, 0, 0,
|
||||||
|
0
|
||||||
|
}
|
||||||
|
));
|
||||||
|
cat.systems.push_back(FurnaceGUISysDef(
|
||||||
|
"Konami SCC", {
|
||||||
|
DIV_SYSTEM_SCC, 64, 0, 0,
|
||||||
|
0
|
||||||
|
}
|
||||||
|
));
|
||||||
|
cat.systems.push_back(FurnaceGUISysDef(
|
||||||
|
"Konami SCC+", {
|
||||||
|
DIV_SYSTEM_SCC_PLUS, 64, 0, 0,
|
||||||
|
0
|
||||||
|
}
|
||||||
|
));
|
||||||
|
cat.systems.push_back(FurnaceGUISysDef(
|
||||||
|
"Namco 163", {
|
||||||
|
DIV_SYSTEM_N163, 64, 0, 0,
|
||||||
|
0
|
||||||
|
}
|
||||||
|
));
|
||||||
|
cat.systems.push_back(FurnaceGUISysDef(
|
||||||
|
"Famicom Disk System (chip)", {
|
||||||
|
DIV_SYSTEM_FDS, 64, 0, 0,
|
||||||
|
0
|
||||||
|
}
|
||||||
|
));
|
||||||
|
cat.systems.push_back(FurnaceGUISysDef(
|
||||||
|
"WonderSwan", {
|
||||||
|
DIV_SYSTEM_SWAN, 64, 0, 0,
|
||||||
|
0
|
||||||
|
}
|
||||||
|
));
|
||||||
|
cat.systems.push_back(FurnaceGUISysDef(
|
||||||
|
"Seta/Allumer X1-010", {
|
||||||
|
DIV_SYSTEM_X1_010, 64, 0, 0,
|
||||||
|
0
|
||||||
|
}
|
||||||
|
));
|
||||||
|
sysCategories.push_back(cat);
|
||||||
|
|
||||||
|
cat=FurnaceGUISysCategory("Specialized","chips/systems with unique sound synthesis methods.");
|
||||||
|
cat.systems.push_back(FurnaceGUISysDef(
|
||||||
|
"MOS Technology SID (6581)", {
|
||||||
|
DIV_SYSTEM_C64_6581, 64, 0, 1,
|
||||||
|
0
|
||||||
|
}
|
||||||
|
));
|
||||||
|
cat.systems.push_back(FurnaceGUISysDef(
|
||||||
|
"MOS Technology SID (8580)", {
|
||||||
|
DIV_SYSTEM_C64_8580, 64, 0, 1,
|
||||||
|
0
|
||||||
|
}
|
||||||
|
));
|
||||||
|
cat.systems.push_back(FurnaceGUISysDef(
|
||||||
|
"Microchip AY8930", {
|
||||||
|
DIV_SYSTEM_AY8930, 64, 0, 0,
|
||||||
|
0
|
||||||
|
}
|
||||||
|
));
|
||||||
|
cat.systems.push_back(FurnaceGUISysDef(
|
||||||
|
"Game Boy", {
|
||||||
|
DIV_SYSTEM_GB, 64, 0, 0,
|
||||||
|
0
|
||||||
|
}
|
||||||
|
));
|
||||||
|
cat.systems.push_back(FurnaceGUISysDef(
|
||||||
|
"Atari Lynx", {
|
||||||
|
DIV_SYSTEM_LYNX, 64, 0, 0,
|
||||||
|
0
|
||||||
|
}
|
||||||
|
));
|
||||||
|
cat.systems.push_back(FurnaceGUISysDef(
|
||||||
|
"Atari TIA", {
|
||||||
|
DIV_SYSTEM_TIA, 64, 0, 0,
|
||||||
|
0
|
||||||
|
}
|
||||||
|
));
|
||||||
|
cat.systems.push_back(FurnaceGUISysDef(
|
||||||
|
"Commander X16 (VERA only)", {
|
||||||
|
DIV_SYSTEM_VERA, 64, 0, 0,
|
||||||
|
0
|
||||||
|
}
|
||||||
|
));
|
||||||
|
cat.systems.push_back(FurnaceGUISysDef(
|
||||||
|
"ZX Spectrum (beeper only)", {
|
||||||
|
DIV_SYSTEM_SFX_BEEPER, 64, 0, 0,
|
||||||
|
0
|
||||||
|
}
|
||||||
|
));
|
||||||
|
if (settings.hiddenSystems) {
|
||||||
|
cat.systems.push_back(FurnaceGUISysDef(
|
||||||
|
"Dummy System", {
|
||||||
|
DIV_SYSTEM_DUMMY, 64, 0, 0,
|
||||||
|
0
|
||||||
|
}
|
||||||
|
));
|
||||||
|
cat.systems.push_back(FurnaceGUISysDef(
|
||||||
|
"tildearrow Sound Unit", {
|
||||||
|
DIV_SYSTEM_SOUND_UNIT, 64, 0, 0,
|
||||||
|
0
|
||||||
|
}
|
||||||
|
));
|
||||||
|
}
|
||||||
|
sysCategories.push_back(cat);
|
||||||
|
|
||||||
|
cat=FurnaceGUISysCategory("Game consoles","let's play some chiptune making games!");
|
||||||
cat.systems.push_back(FurnaceGUISysDef(
|
cat.systems.push_back(FurnaceGUISysDef(
|
||||||
"Sega Genesis", {
|
"Sega Genesis", {
|
||||||
DIV_SYSTEM_YM2612, 64, 0, 0,
|
DIV_SYSTEM_YM2612, 64, 0, 0,
|
||||||
|
|
@ -339,7 +543,7 @@ void FurnaceGUI::initSystemPresets() {
|
||||||
));
|
));
|
||||||
sysCategories.push_back(cat);
|
sysCategories.push_back(cat);
|
||||||
|
|
||||||
cat=FurnaceGUISysCategory("Computers");
|
cat=FurnaceGUISysCategory("Computers","let's get to work on chiptune today.");
|
||||||
cat.systems.push_back(FurnaceGUISysDef(
|
cat.systems.push_back(FurnaceGUISysDef(
|
||||||
"Commodore PET", {
|
"Commodore PET", {
|
||||||
DIV_SYSTEM_PET, 64, 0, 0,
|
DIV_SYSTEM_PET, 64, 0, 0,
|
||||||
|
|
@ -411,6 +615,20 @@ void FurnaceGUI::initSystemPresets() {
|
||||||
0
|
0
|
||||||
}
|
}
|
||||||
));
|
));
|
||||||
|
cat.systems.push_back(FurnaceGUISysDef(
|
||||||
|
"MSX + MSX-AUDIO", {
|
||||||
|
DIV_SYSTEM_AY8910, 64, 0, 16,
|
||||||
|
DIV_SYSTEM_Y8950, 64, 0, 0,
|
||||||
|
0
|
||||||
|
}
|
||||||
|
));
|
||||||
|
cat.systems.push_back(FurnaceGUISysDef(
|
||||||
|
"MSX + MSX-AUDIO (drums mode)", {
|
||||||
|
DIV_SYSTEM_AY8910, 64, 0, 16,
|
||||||
|
DIV_SYSTEM_Y8950_DRUMS, 64, 0, 0,
|
||||||
|
0
|
||||||
|
}
|
||||||
|
));
|
||||||
cat.systems.push_back(FurnaceGUISysDef(
|
cat.systems.push_back(FurnaceGUISysDef(
|
||||||
"MSX + MSX-MUSIC", {
|
"MSX + MSX-MUSIC", {
|
||||||
DIV_SYSTEM_AY8910, 64, 0, 16,
|
DIV_SYSTEM_AY8910, 64, 0, 16,
|
||||||
|
|
@ -445,6 +663,24 @@ void FurnaceGUI::initSystemPresets() {
|
||||||
0
|
0
|
||||||
}
|
}
|
||||||
));
|
));
|
||||||
|
cat.systems.push_back(FurnaceGUISysDef(
|
||||||
|
"NEC PC-98 (with PC-9801-26K; extended channel 3)", {
|
||||||
|
DIV_SYSTEM_OPN_EXT, 64, 0, 3,
|
||||||
|
0
|
||||||
|
}
|
||||||
|
));
|
||||||
|
cat.systems.push_back(FurnaceGUISysDef(
|
||||||
|
"NEC PC-98 (with PC-9801-86)", {
|
||||||
|
DIV_SYSTEM_PC98, 64, 0, 3,
|
||||||
|
0
|
||||||
|
}
|
||||||
|
));
|
||||||
|
cat.systems.push_back(FurnaceGUISysDef(
|
||||||
|
"NEC PC-98 (with PC-9801-86; extended channel 3)", {
|
||||||
|
DIV_SYSTEM_PC98_EXT, 64, 0, 3,
|
||||||
|
0
|
||||||
|
}
|
||||||
|
));
|
||||||
cat.systems.push_back(FurnaceGUISysDef(
|
cat.systems.push_back(FurnaceGUISysDef(
|
||||||
"ZX Spectrum (48K)", {
|
"ZX Spectrum (48K)", {
|
||||||
DIV_SYSTEM_AY8910, 64, 0, 2,
|
DIV_SYSTEM_AY8910, 64, 0, 2,
|
||||||
|
|
@ -611,7 +847,7 @@ void FurnaceGUI::initSystemPresets() {
|
||||||
));
|
));
|
||||||
sysCategories.push_back(cat);
|
sysCategories.push_back(cat);
|
||||||
|
|
||||||
cat=FurnaceGUISysCategory("Arcade systems");
|
cat=FurnaceGUISysCategory("Arcade systems","INSERT COIN");
|
||||||
cat.systems.push_back(FurnaceGUISysDef(
|
cat.systems.push_back(FurnaceGUISysDef(
|
||||||
"Bally Midway MCR", {
|
"Bally Midway MCR", {
|
||||||
DIV_SYSTEM_AY8910, 64, 0, 0,
|
DIV_SYSTEM_AY8910, 64, 0, 0,
|
||||||
|
|
@ -693,7 +929,7 @@ void FurnaceGUI::initSystemPresets() {
|
||||||
));
|
));
|
||||||
sysCategories.push_back(cat);
|
sysCategories.push_back(cat);
|
||||||
|
|
||||||
cat=FurnaceGUISysCategory("DefleMask-compatible");
|
cat=FurnaceGUISysCategory("DefleMask-compatible","these configurations are compatible with DefleMask.\nselect this if you need to save as .dmf or work with that program.");
|
||||||
cat.systems.push_back(FurnaceGUISysDef(
|
cat.systems.push_back(FurnaceGUISysDef(
|
||||||
"Sega Genesis", {
|
"Sega Genesis", {
|
||||||
DIV_SYSTEM_YM2612, 64, 0, 0,
|
DIV_SYSTEM_YM2612, 64, 0, 0,
|
||||||
|
|
|
||||||
|
|
@ -883,6 +883,33 @@ void FurnaceGUI::drawSettings() {
|
||||||
ImGui::Text("FDS core");
|
ImGui::Text("FDS core");
|
||||||
ImGui::SameLine();
|
ImGui::SameLine();
|
||||||
ImGui::Combo("##FDSCore",&settings.fdsCore,nesCores,2);
|
ImGui::Combo("##FDSCore",&settings.fdsCore,nesCores,2);
|
||||||
|
|
||||||
|
ImGui::Separator();
|
||||||
|
ImGui::Text("Sample ROMs:");
|
||||||
|
|
||||||
|
ImGui::Text("OPL4 YRW801 path");
|
||||||
|
ImGui::SameLine();
|
||||||
|
ImGui::InputText("##YRW801Path",&settings.yrw801Path);
|
||||||
|
ImGui::SameLine();
|
||||||
|
if (ImGui::Button(ICON_FA_FOLDER "##YRW801Load")) {
|
||||||
|
openFileDialog(GUI_FILE_YRW801_ROM_OPEN);
|
||||||
|
}
|
||||||
|
|
||||||
|
ImGui::Text("MultiPCM TG100 path");
|
||||||
|
ImGui::SameLine();
|
||||||
|
ImGui::InputText("##TG100Path",&settings.tg100Path);
|
||||||
|
ImGui::SameLine();
|
||||||
|
if (ImGui::Button(ICON_FA_FOLDER "##TG100Load")) {
|
||||||
|
openFileDialog(GUI_FILE_TG100_ROM_OPEN);
|
||||||
|
}
|
||||||
|
|
||||||
|
ImGui::Text("MultiPCM MU5 path");
|
||||||
|
ImGui::SameLine();
|
||||||
|
ImGui::InputText("##MU5Path",&settings.mu5Path);
|
||||||
|
ImGui::SameLine();
|
||||||
|
if (ImGui::Button(ICON_FA_FOLDER "##MU5Load")) {
|
||||||
|
openFileDialog(GUI_FILE_MU5_ROM_OPEN);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
ImGui::EndChild();
|
ImGui::EndChild();
|
||||||
ImGui::EndTabItem();
|
ImGui::EndTabItem();
|
||||||
|
|
@ -951,6 +978,19 @@ void FurnaceGUI::drawSettings() {
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
bool loadChineseB=settings.loadChinese;
|
||||||
|
if (ImGui::Checkbox("Display Chinese (Simplified) characters",&loadChineseB)) {
|
||||||
|
settings.loadChinese=loadChineseB;
|
||||||
|
}
|
||||||
|
if (ImGui::IsItemHovered()) {
|
||||||
|
ImGui::SetTooltip(
|
||||||
|
"Only toggle this option if you have enough graphics memory.\n"
|
||||||
|
"This is a temporary solution until dynamic font atlas is implemented in Dear ImGui.\n\n"
|
||||||
|
"请在确保你有足够的显存后再启动此设定\n"
|
||||||
|
"这是一个在ImGui实现动态字体加载之前的临时解决方案"
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
ImGui::Separator();
|
ImGui::Separator();
|
||||||
|
|
||||||
ImGui::Text("Orders row number format:");
|
ImGui::Text("Orders row number format:");
|
||||||
|
|
@ -1147,6 +1187,11 @@ void FurnaceGUI::drawSettings() {
|
||||||
settings.sampleLayout=sampleLayoutB;
|
settings.sampleLayout=sampleLayoutB;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
bool oldMacroVSliderB=settings.oldMacroVSlider;
|
||||||
|
if (ImGui::Checkbox("Use classic macro editor vertical slider",&oldMacroVSliderB)) {
|
||||||
|
settings.oldMacroVSlider=oldMacroVSliderB;
|
||||||
|
}
|
||||||
|
|
||||||
bool roundedWindowsB=settings.roundedWindows;
|
bool roundedWindowsB=settings.roundedWindows;
|
||||||
if (ImGui::Checkbox("Rounded window corners",&roundedWindowsB)) {
|
if (ImGui::Checkbox("Rounded window corners",&roundedWindowsB)) {
|
||||||
settings.roundedWindows=roundedWindowsB;
|
settings.roundedWindows=roundedWindowsB;
|
||||||
|
|
@ -1784,6 +1829,9 @@ void FurnaceGUI::syncSettings() {
|
||||||
settings.saaCore=e->getConfInt("saaCore",1);
|
settings.saaCore=e->getConfInt("saaCore",1);
|
||||||
settings.nesCore=e->getConfInt("nesCore",0);
|
settings.nesCore=e->getConfInt("nesCore",0);
|
||||||
settings.fdsCore=e->getConfInt("fdsCore",0);
|
settings.fdsCore=e->getConfInt("fdsCore",0);
|
||||||
|
settings.yrw801Path=e->getConfString("yrw801Path","");
|
||||||
|
settings.tg100Path=e->getConfString("tg100Path","");
|
||||||
|
settings.mu5Path=e->getConfString("mu5Path","");
|
||||||
settings.mainFont=e->getConfInt("mainFont",0);
|
settings.mainFont=e->getConfInt("mainFont",0);
|
||||||
settings.patFont=e->getConfInt("patFont",0);
|
settings.patFont=e->getConfInt("patFont",0);
|
||||||
settings.mainFontPath=e->getConfString("mainFontPath","");
|
settings.mainFontPath=e->getConfString("mainFontPath","");
|
||||||
|
|
@ -1820,6 +1868,7 @@ void FurnaceGUI::syncSettings() {
|
||||||
settings.roundedButtons=e->getConfInt("roundedButtons",1);
|
settings.roundedButtons=e->getConfInt("roundedButtons",1);
|
||||||
settings.roundedMenus=e->getConfInt("roundedMenus",0);
|
settings.roundedMenus=e->getConfInt("roundedMenus",0);
|
||||||
settings.loadJapanese=e->getConfInt("loadJapanese",0);
|
settings.loadJapanese=e->getConfInt("loadJapanese",0);
|
||||||
|
settings.loadChinese=e->getConfInt("loadChinese",0);
|
||||||
settings.fmLayout=e->getConfInt("fmLayout",0);
|
settings.fmLayout=e->getConfInt("fmLayout",0);
|
||||||
settings.sampleLayout=e->getConfInt("sampleLayout",0);
|
settings.sampleLayout=e->getConfInt("sampleLayout",0);
|
||||||
settings.waveLayout=e->getConfInt("waveLayout",0);
|
settings.waveLayout=e->getConfInt("waveLayout",0);
|
||||||
|
|
@ -1849,6 +1898,7 @@ void FurnaceGUI::syncSettings() {
|
||||||
settings.hiddenSystems=e->getConfInt("hiddenSystems",0);
|
settings.hiddenSystems=e->getConfInt("hiddenSystems",0);
|
||||||
settings.horizontalDataView=e->getConfInt("horizontalDataView",0);
|
settings.horizontalDataView=e->getConfInt("horizontalDataView",0);
|
||||||
settings.noMultiSystem=e->getConfInt("noMultiSystem",0);
|
settings.noMultiSystem=e->getConfInt("noMultiSystem",0);
|
||||||
|
settings.oldMacroVSlider=e->getConfInt("oldMacroVSlider",0);
|
||||||
|
|
||||||
clampSetting(settings.mainFontSize,2,96);
|
clampSetting(settings.mainFontSize,2,96);
|
||||||
clampSetting(settings.patFontSize,2,96);
|
clampSetting(settings.patFontSize,2,96);
|
||||||
|
|
@ -1895,6 +1945,7 @@ void FurnaceGUI::syncSettings() {
|
||||||
clampSetting(settings.roundedButtons,0,1);
|
clampSetting(settings.roundedButtons,0,1);
|
||||||
clampSetting(settings.roundedMenus,0,1);
|
clampSetting(settings.roundedMenus,0,1);
|
||||||
clampSetting(settings.loadJapanese,0,1);
|
clampSetting(settings.loadJapanese,0,1);
|
||||||
|
clampSetting(settings.loadChinese,0,1);
|
||||||
clampSetting(settings.fmLayout,0,3);
|
clampSetting(settings.fmLayout,0,3);
|
||||||
clampSetting(settings.susPosition,0,1);
|
clampSetting(settings.susPosition,0,1);
|
||||||
clampSetting(settings.effectCursorDir,0,2);
|
clampSetting(settings.effectCursorDir,0,2);
|
||||||
|
|
@ -1920,7 +1971,8 @@ void FurnaceGUI::syncSettings() {
|
||||||
clampSetting(settings.moveWindowTitle,0,1);
|
clampSetting(settings.moveWindowTitle,0,1);
|
||||||
clampSetting(settings.hiddenSystems,0,1);
|
clampSetting(settings.hiddenSystems,0,1);
|
||||||
clampSetting(settings.horizontalDataView,0,1);
|
clampSetting(settings.horizontalDataView,0,1);
|
||||||
clampSetting(settings.noMultiSystem,0,1)
|
clampSetting(settings.noMultiSystem,0,1);
|
||||||
|
clampSetting(settings.oldMacroVSlider,0,1);
|
||||||
|
|
||||||
settings.initialSys=e->decodeSysDesc(e->getConfString("initialSys",""));
|
settings.initialSys=e->decodeSysDesc(e->getConfString("initialSys",""));
|
||||||
if (settings.initialSys.size()<4) {
|
if (settings.initialSys.size()<4) {
|
||||||
|
|
@ -1953,6 +2005,10 @@ void FurnaceGUI::syncSettings() {
|
||||||
}
|
}
|
||||||
|
|
||||||
void FurnaceGUI::commitSettings() {
|
void FurnaceGUI::commitSettings() {
|
||||||
|
bool sampleROMsChanged = settings.yrw801Path!=e->getConfString("yrw801Path","") ||
|
||||||
|
settings.tg100Path!=e->getConfString("tg100Path","") ||
|
||||||
|
settings.mu5Path!=e->getConfString("mu5Path","");
|
||||||
|
|
||||||
e->setConf("mainFontSize",settings.mainFontSize);
|
e->setConf("mainFontSize",settings.mainFontSize);
|
||||||
e->setConf("patFontSize",settings.patFontSize);
|
e->setConf("patFontSize",settings.patFontSize);
|
||||||
e->setConf("iconSize",settings.iconSize);
|
e->setConf("iconSize",settings.iconSize);
|
||||||
|
|
@ -1968,6 +2024,9 @@ void FurnaceGUI::commitSettings() {
|
||||||
e->setConf("saaCore",settings.saaCore);
|
e->setConf("saaCore",settings.saaCore);
|
||||||
e->setConf("nesCore",settings.nesCore);
|
e->setConf("nesCore",settings.nesCore);
|
||||||
e->setConf("fdsCore",settings.fdsCore);
|
e->setConf("fdsCore",settings.fdsCore);
|
||||||
|
e->setConf("yrw801Path",settings.yrw801Path);
|
||||||
|
e->setConf("tg100Path",settings.tg100Path);
|
||||||
|
e->setConf("mu5Path",settings.mu5Path);
|
||||||
e->setConf("mainFont",settings.mainFont);
|
e->setConf("mainFont",settings.mainFont);
|
||||||
e->setConf("patFont",settings.patFont);
|
e->setConf("patFont",settings.patFont);
|
||||||
e->setConf("mainFontPath",settings.mainFontPath);
|
e->setConf("mainFontPath",settings.mainFontPath);
|
||||||
|
|
@ -2004,6 +2063,7 @@ void FurnaceGUI::commitSettings() {
|
||||||
e->setConf("roundedButtons",settings.roundedButtons);
|
e->setConf("roundedButtons",settings.roundedButtons);
|
||||||
e->setConf("roundedMenus",settings.roundedMenus);
|
e->setConf("roundedMenus",settings.roundedMenus);
|
||||||
e->setConf("loadJapanese",settings.loadJapanese);
|
e->setConf("loadJapanese",settings.loadJapanese);
|
||||||
|
e->setConf("loadChinese",settings.loadChinese);
|
||||||
e->setConf("fmLayout",settings.fmLayout);
|
e->setConf("fmLayout",settings.fmLayout);
|
||||||
e->setConf("sampleLayout",settings.sampleLayout);
|
e->setConf("sampleLayout",settings.sampleLayout);
|
||||||
e->setConf("waveLayout",settings.waveLayout);
|
e->setConf("waveLayout",settings.waveLayout);
|
||||||
|
|
@ -2034,6 +2094,7 @@ void FurnaceGUI::commitSettings() {
|
||||||
e->setConf("initialSys",e->encodeSysDesc(settings.initialSys));
|
e->setConf("initialSys",e->encodeSysDesc(settings.initialSys));
|
||||||
e->setConf("horizontalDataView",settings.horizontalDataView);
|
e->setConf("horizontalDataView",settings.horizontalDataView);
|
||||||
e->setConf("noMultiSystem",settings.noMultiSystem);
|
e->setConf("noMultiSystem",settings.noMultiSystem);
|
||||||
|
e->setConf("oldMacroVSlider",settings.oldMacroVSlider);
|
||||||
|
|
||||||
// colors
|
// colors
|
||||||
for (int i=0; i<GUI_COLOR_MAX; i++) {
|
for (int i=0; i<GUI_COLOR_MAX; i++) {
|
||||||
|
|
@ -2055,6 +2116,12 @@ void FurnaceGUI::commitSettings() {
|
||||||
|
|
||||||
e->saveConf();
|
e->saveConf();
|
||||||
|
|
||||||
|
if (sampleROMsChanged) {
|
||||||
|
if (e->loadSampleROMs()) {
|
||||||
|
showError(e->getLastError());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
if (!e->switchMaster()) {
|
if (!e->switchMaster()) {
|
||||||
showError("could not initialize audio!");
|
showError("could not initialize audio!");
|
||||||
}
|
}
|
||||||
|
|
@ -2587,6 +2654,9 @@ void FurnaceGUI::applyUISettings(bool updateFonts) {
|
||||||
if (settings.loadJapanese) {
|
if (settings.loadJapanese) {
|
||||||
range.AddRanges(ImGui::GetIO().Fonts->GetGlyphRangesJapanese());
|
range.AddRanges(ImGui::GetIO().Fonts->GetGlyphRangesJapanese());
|
||||||
}
|
}
|
||||||
|
if (settings.loadChinese) {
|
||||||
|
range.AddRanges(ImGui::GetIO().Fonts->GetGlyphRangesChineseSimplifiedCommon());
|
||||||
|
}
|
||||||
// I'm terribly sorry
|
// I'm terribly sorry
|
||||||
range.UsedChars[0x80>>5]=0;
|
range.UsedChars[0x80>>5]=0;
|
||||||
|
|
||||||
|
|
|
||||||
Loading…
Reference in a new issue