mirror of
https://github.com/tildearrow/furnace.git
synced 2024-11-26 22:43:01 +00:00
Merge branch 'master' of https://github.com/tildearrow/furnace into ym2610b
This commit is contained in:
commit
6d36a8fdd2
5 changed files with 137 additions and 96 deletions
|
@ -4,8 +4,12 @@ while Furnace works directly with the .dmf format, I had to create a new format
|
||||||
|
|
||||||
this document has the goal of detailing the format.
|
this document has the goal of detailing the format.
|
||||||
|
|
||||||
|
**notice:** GitHub's Markdown formatter may break on this file as it doesn't seem to treat tables correctly.
|
||||||
|
|
||||||
# information
|
# information
|
||||||
|
|
||||||
|
files may be zlib-compressed, but Furnace accepts uncompressed files as well.
|
||||||
|
|
||||||
all numbers are little-endian.
|
all numbers are little-endian.
|
||||||
|
|
||||||
the following fields may be found in "size":
|
the following fields may be found in "size":
|
||||||
|
@ -71,6 +75,7 @@ the format versions are:
|
||||||
|
|
||||||
the header is 32 bytes long.
|
the header is 32 bytes long.
|
||||||
|
|
||||||
|
```
|
||||||
size | description
|
size | description
|
||||||
-----|------------------------------------
|
-----|------------------------------------
|
||||||
16 | "-Furnace module-" format magic
|
16 | "-Furnace module-" format magic
|
||||||
|
@ -78,9 +83,11 @@ size | description
|
||||||
2 | reserved
|
2 | reserved
|
||||||
4 | song info pointer
|
4 | song info pointer
|
||||||
8 | reserved
|
8 | reserved
|
||||||
|
```
|
||||||
|
|
||||||
# song info
|
# song info
|
||||||
|
|
||||||
|
```
|
||||||
size | description
|
size | description
|
||||||
-----|------------------------------------
|
-----|------------------------------------
|
||||||
4 | "INFO" block ID
|
4 | "INFO" block ID
|
||||||
|
@ -208,9 +215,11 @@ size | description
|
||||||
STR | song comment
|
STR | song comment
|
||||||
4f | master volume, 1.0f=100% (>=59)
|
4f | master volume, 1.0f=100% (>=59)
|
||||||
| this is 2.0f for modules before 59
|
| this is 2.0f for modules before 59
|
||||||
|
```
|
||||||
|
|
||||||
# instrument
|
# instrument
|
||||||
|
|
||||||
|
```
|
||||||
size | description
|
size | description
|
||||||
-----|------------------------------------
|
-----|------------------------------------
|
||||||
4 | "INST" block ID
|
4 | "INST" block ID
|
||||||
|
@ -418,9 +427,11 @@ size | description
|
||||||
4 | DT macro release
|
4 | DT macro release
|
||||||
4 | D2R macro release
|
4 | D2R macro release
|
||||||
4 | SSG-EG macro release
|
4 | SSG-EG macro release
|
||||||
|
```
|
||||||
|
|
||||||
# wavetable
|
# wavetable
|
||||||
|
|
||||||
|
```
|
||||||
size | description
|
size | description
|
||||||
-----|------------------------------------
|
-----|------------------------------------
|
||||||
4 | "WAVE" block ID
|
4 | "WAVE" block ID
|
||||||
|
@ -430,9 +441,11 @@ size | description
|
||||||
4 | wavetable min
|
4 | wavetable min
|
||||||
4 | wavetable max
|
4 | wavetable max
|
||||||
4?? | wavetable data
|
4?? | wavetable data
|
||||||
|
```
|
||||||
|
|
||||||
# sample
|
# sample
|
||||||
|
|
||||||
|
```
|
||||||
size | description
|
size | description
|
||||||
-----|------------------------------------
|
-----|------------------------------------
|
||||||
4 | "SMPL" block ID
|
4 | "SMPL" block ID
|
||||||
|
@ -460,9 +473,11 @@ size | description
|
||||||
??? | sample data
|
??? | sample data
|
||||||
| - version<58 size is length*2
|
| - version<58 size is length*2
|
||||||
| - version>=58 size is length
|
| - version>=58 size is length
|
||||||
|
```
|
||||||
|
|
||||||
# pattern
|
# pattern
|
||||||
|
|
||||||
|
```
|
||||||
size | description
|
size | description
|
||||||
-----|------------------------------------
|
-----|------------------------------------
|
||||||
4 | "PATR" block ID
|
4 | "PATR" block ID
|
||||||
|
@ -479,11 +494,13 @@ size | description
|
||||||
| - volume
|
| - volume
|
||||||
| - effect and effect data...
|
| - effect and effect data...
|
||||||
STR | pattern name (>=51)
|
STR | pattern name (>=51)
|
||||||
|
```
|
||||||
|
|
||||||
# the Furnace instrument format (.fui)
|
# the Furnace instrument format (.fui)
|
||||||
|
|
||||||
the instrument format is pretty similar to the file format, but it also stores wavetables and samples used by the instrument.
|
the instrument format is pretty similar to the file format, but it also stores wavetables and samples used by the instrument.
|
||||||
|
|
||||||
|
```
|
||||||
size | description
|
size | description
|
||||||
-----|------------------------------------
|
-----|------------------------------------
|
||||||
16 | "-Furnace instr.-" format magic
|
16 | "-Furnace instr.-" format magic
|
||||||
|
@ -495,6 +512,7 @@ size | description
|
||||||
4 | reserved
|
4 | reserved
|
||||||
4?? | pointers to wavetables
|
4?? | pointers to wavetables
|
||||||
4?? | pointers to samples
|
4?? | pointers to samples
|
||||||
|
```
|
||||||
|
|
||||||
instrument data follows.
|
instrument data follows.
|
||||||
|
|
||||||
|
@ -502,10 +520,12 @@ instrument data follows.
|
||||||
|
|
||||||
similar to the instrument format...
|
similar to the instrument format...
|
||||||
|
|
||||||
|
```
|
||||||
size | description
|
size | description
|
||||||
-----|------------------------------------
|
-----|------------------------------------
|
||||||
16 | "-Furnace waveta-" format magic
|
16 | "-Furnace waveta-" format magic
|
||||||
2 | format version
|
2 | format version
|
||||||
2 | reserved
|
2 | reserved
|
||||||
|
```
|
||||||
|
|
||||||
wavetable data follows.
|
wavetable data follows.
|
||||||
|
|
|
@ -80,29 +80,31 @@ void DivPlatformOPLL::acquire_nuked(short* bufL, short* bufR, size_t start, size
|
||||||
static int os;
|
static int os;
|
||||||
|
|
||||||
for (size_t h=start; h<start+len; h++) {
|
for (size_t h=start; h<start+len; h++) {
|
||||||
if (!writes.empty() && --delay<0) {
|
os=0;
|
||||||
// 84 is safe value
|
for (int i=0; i<9; i++) {
|
||||||
QueuedWrite& w=writes.front();
|
if (!writes.empty() && --delay<0) {
|
||||||
if (w.addrOrVal) {
|
// 84 is safe value
|
||||||
OPLL_Write(&fm,1,w.val);
|
QueuedWrite& w=writes.front();
|
||||||
//printf("write: %x = %.2x\n",w.addr,w.val);
|
if (w.addrOrVal) {
|
||||||
regPool[w.addr&0xff]=w.val;
|
OPLL_Write(&fm,1,w.val);
|
||||||
writes.pop();
|
//printf("write: %x = %.2x\n",w.addr,w.val);
|
||||||
delay=21;
|
regPool[w.addr&0xff]=w.val;
|
||||||
} else {
|
writes.pop();
|
||||||
//printf("busycounter: %d\n",lastBusy);
|
delay=21;
|
||||||
OPLL_Write(&fm,0,w.addr);
|
} else {
|
||||||
w.addrOrVal=true;
|
//printf("busycounter: %d\n",lastBusy);
|
||||||
delay=3;
|
OPLL_Write(&fm,0,w.addr);
|
||||||
|
w.addrOrVal=true;
|
||||||
|
delay=3;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
|
||||||
OPLL_Clock(&fm,o);
|
OPLL_Clock(&fm,o);
|
||||||
os=(o[0]+o[1])<<7;
|
os+=(o[0]+o[1]);
|
||||||
|
}
|
||||||
|
os*=50;
|
||||||
if (os<-32768) os=-32768;
|
if (os<-32768) os=-32768;
|
||||||
if (os>32767) os=32767;
|
if (os>32767) os=32767;
|
||||||
//printf("%d\n",o[0]);
|
|
||||||
|
|
||||||
bufL[h]=os;
|
bufL[h]=os;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -239,7 +241,12 @@ void DivPlatformOPLL::tick() {
|
||||||
}*/
|
}*/
|
||||||
|
|
||||||
if (chan[i].keyOn || chan[i].keyOff) {
|
if (chan[i].keyOn || chan[i].keyOff) {
|
||||||
immWrite(0x20+i,(chan[i].freqH)|(chan[i].state.alg?0x20:0));
|
if (chan[i].drums) {
|
||||||
|
drumState&=~(0x10>>(chan[i].note%12));
|
||||||
|
immWrite(0x0e,0x20|drumState);
|
||||||
|
} else {
|
||||||
|
immWrite(0x20+i,(chan[i].freqH)/*|(chan[i].state.alg?0x20:0)*/);
|
||||||
|
}
|
||||||
//chan[i].keyOn=false;
|
//chan[i].keyOn=false;
|
||||||
chan[i].keyOff=false;
|
chan[i].keyOff=false;
|
||||||
}
|
}
|
||||||
|
@ -259,9 +266,16 @@ void DivPlatformOPLL::tick() {
|
||||||
int freqt=toFreq(chan[i].freq);
|
int freqt=toFreq(chan[i].freq);
|
||||||
chan[i].freqH=freqt>>8;
|
chan[i].freqH=freqt>>8;
|
||||||
chan[i].freqL=freqt&0xff;
|
chan[i].freqL=freqt&0xff;
|
||||||
immWrite(0x10+i,freqt&0xff);
|
if (!chan[i].drums) {
|
||||||
|
immWrite(0x10+i,freqt&0xff);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
if (chan[i].keyOn || chan[i].freqChanged) {
|
if (chan[i].keyOn && chan[i].drums) {
|
||||||
|
//printf("%d\n",chan[i].note%12);
|
||||||
|
drumState|=(0x10>>(chan[i].note%12));
|
||||||
|
immWrite(0x0e,0x20|drumState);
|
||||||
|
chan[i].keyOn=false;
|
||||||
|
} else if (chan[i].keyOn || chan[i].freqChanged) {
|
||||||
//immWrite(0x28,0xf0|konOffs[i]);
|
//immWrite(0x28,0xf0|konOffs[i]);
|
||||||
immWrite(0x20+i,(chan[i].freqH)|(chan[i].active<<4)|(chan[i].state.alg?0x20:0));
|
immWrite(0x20+i,(chan[i].freqH)|(chan[i].active<<4)|(chan[i].state.alg?0x20:0));
|
||||||
chan[i].keyOn=false;
|
chan[i].keyOn=false;
|
||||||
|
@ -359,7 +373,22 @@ int DivPlatformOPLL::dispatch(DivCommand c) {
|
||||||
rWrite(0x06,(mod.sl<<4)|(mod.rr));
|
rWrite(0x06,(mod.sl<<4)|(mod.rr));
|
||||||
rWrite(0x07,(car.sl<<4)|(car.rr));
|
rWrite(0x07,(car.sl<<4)|(car.rr));
|
||||||
}
|
}
|
||||||
rWrite(0x30+c.chan,(15-(chan[c.chan].outVol*(15-chan[c.chan].state.op[1].tl))/15)|(chan[c.chan].state.opllPreset<<4));
|
if (chan[c.chan].state.opllPreset==16) { // compatible drums mode
|
||||||
|
chan[c.chan].drums=true;
|
||||||
|
immWrite(0x16,0x20);
|
||||||
|
immWrite(0x26,0x05);
|
||||||
|
immWrite(0x16,0x20);
|
||||||
|
immWrite(0x26,0x05);
|
||||||
|
immWrite(0x17,0x50);
|
||||||
|
immWrite(0x27,0x05);
|
||||||
|
immWrite(0x17,0x50);
|
||||||
|
immWrite(0x27,0x05);
|
||||||
|
immWrite(0x18,0xC0);
|
||||||
|
immWrite(0x28,0x01);
|
||||||
|
} else {
|
||||||
|
chan[c.chan].drums=false;
|
||||||
|
rWrite(0x30+c.chan,(15-(chan[c.chan].outVol*(15-chan[c.chan].state.op[1].tl))/15)|(chan[c.chan].state.opllPreset<<4));
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
chan[c.chan].insChanged=false;
|
chan[c.chan].insChanged=false;
|
||||||
|
@ -367,6 +396,29 @@ int DivPlatformOPLL::dispatch(DivCommand c) {
|
||||||
if (c.value!=DIV_NOTE_NULL) {
|
if (c.value!=DIV_NOTE_NULL) {
|
||||||
chan[c.chan].baseFreq=NOTE_FREQUENCY(c.value);
|
chan[c.chan].baseFreq=NOTE_FREQUENCY(c.value);
|
||||||
chan[c.chan].note=c.value;
|
chan[c.chan].note=c.value;
|
||||||
|
|
||||||
|
if (chan[c.chan].drums) {
|
||||||
|
switch (chan[c.chan].note%12) {
|
||||||
|
case 0: // kick
|
||||||
|
drumVol[0]=(15-(chan[c.chan].outVol*(15-chan[c.chan].state.op[1].tl))/15);
|
||||||
|
break;
|
||||||
|
case 1: // snare
|
||||||
|
drumVol[1]=(15-(chan[c.chan].outVol*(15-chan[c.chan].state.op[1].tl))/15);
|
||||||
|
break;
|
||||||
|
case 2: // tom
|
||||||
|
drumVol[2]=(15-(chan[c.chan].outVol*(15-chan[c.chan].state.op[1].tl))/15);
|
||||||
|
break;
|
||||||
|
case 3: // top
|
||||||
|
drumVol[3]=(15-(chan[c.chan].outVol*(15-chan[c.chan].state.op[1].tl))/15);
|
||||||
|
break;
|
||||||
|
default: // hi-hat
|
||||||
|
drumVol[4]=(15-(chan[c.chan].outVol*(15-chan[c.chan].state.op[1].tl))/15);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
rWrite(0x36,drumVol[0]);
|
||||||
|
rWrite(0x37,drumVol[1]|(drumVol[4]<<4));
|
||||||
|
rWrite(0x38,drumVol[3]|(drumVol[2]<<4));
|
||||||
|
}
|
||||||
chan[c.chan].freqChanged=true;
|
chan[c.chan].freqChanged=true;
|
||||||
}
|
}
|
||||||
chan[c.chan].keyOn=true;
|
chan[c.chan].keyOn=true;
|
||||||
|
@ -392,7 +444,9 @@ int DivPlatformOPLL::dispatch(DivCommand c) {
|
||||||
if (!chan[c.chan].std.hasVol) {
|
if (!chan[c.chan].std.hasVol) {
|
||||||
chan[c.chan].outVol=c.value;
|
chan[c.chan].outVol=c.value;
|
||||||
}
|
}
|
||||||
rWrite(0x30+c.chan,(15-(chan[c.chan].outVol*(15-chan[c.chan].state.op[1].tl))/15)|(chan[c.chan].state.opllPreset<<4));
|
if (!chan[c.chan].drums) {
|
||||||
|
rWrite(0x30+c.chan,(15-(chan[c.chan].outVol*(15-chan[c.chan].state.op[1].tl))/15)|(chan[c.chan].state.opllPreset<<4));
|
||||||
|
}
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
case DIV_CMD_GET_VOLUME: {
|
case DIV_CMD_GET_VOLUME: {
|
||||||
|
@ -570,6 +624,13 @@ void DivPlatformOPLL::reset() {
|
||||||
}
|
}
|
||||||
|
|
||||||
lastBusy=60;
|
lastBusy=60;
|
||||||
|
drumState=0;
|
||||||
|
|
||||||
|
drumVol[0]=0;
|
||||||
|
drumVol[1]=0;
|
||||||
|
drumVol[2]=0;
|
||||||
|
drumVol[3]=0;
|
||||||
|
drumVol[4]=0;
|
||||||
|
|
||||||
delay=0;
|
delay=0;
|
||||||
}
|
}
|
||||||
|
@ -619,7 +680,7 @@ void DivPlatformOPLL::setFlags(unsigned int flags) {
|
||||||
} else {
|
} else {
|
||||||
chipClock=COLOR_NTSC/4.0;
|
chipClock=COLOR_NTSC/4.0;
|
||||||
}
|
}
|
||||||
rate=chipClock;
|
rate=chipClock/9;
|
||||||
}
|
}
|
||||||
|
|
||||||
int DivPlatformOPLL::init(DivEngine* p, int channels, int sugRate, unsigned int flags) {
|
int DivPlatformOPLL::init(DivEngine* p, int channels, int sugRate, unsigned int flags) {
|
||||||
|
|
|
@ -35,7 +35,7 @@ class DivPlatformOPLL: public DivDispatch {
|
||||||
unsigned char freqH, freqL;
|
unsigned char freqH, freqL;
|
||||||
int freq, baseFreq, pitch, note;
|
int freq, baseFreq, pitch, note;
|
||||||
unsigned char ins;
|
unsigned char ins;
|
||||||
bool active, insChanged, freqChanged, keyOn, keyOff, portaPause, furnaceDac, inPorta;
|
bool active, insChanged, freqChanged, keyOn, keyOff, drums, portaPause, furnaceDac, inPorta;
|
||||||
int vol, outVol;
|
int vol, outVol;
|
||||||
unsigned char pan;
|
unsigned char pan;
|
||||||
Channel():
|
Channel():
|
||||||
|
@ -51,6 +51,7 @@ class DivPlatformOPLL: public DivDispatch {
|
||||||
freqChanged(false),
|
freqChanged(false),
|
||||||
keyOn(false),
|
keyOn(false),
|
||||||
keyOff(false),
|
keyOff(false),
|
||||||
|
drums(false),
|
||||||
portaPause(false),
|
portaPause(false),
|
||||||
furnaceDac(false),
|
furnaceDac(false),
|
||||||
inPorta(false),
|
inPorta(false),
|
||||||
|
@ -69,6 +70,8 @@ class DivPlatformOPLL: public DivDispatch {
|
||||||
opll_t fm;
|
opll_t fm;
|
||||||
int delay;
|
int delay;
|
||||||
unsigned char lastBusy;
|
unsigned char lastBusy;
|
||||||
|
unsigned char drumState;
|
||||||
|
unsigned char drumVol[5];
|
||||||
|
|
||||||
unsigned char regPool[256];
|
unsigned char regPool[256];
|
||||||
|
|
||||||
|
|
|
@ -601,8 +601,8 @@ static void state_normal_update(struct qsound_chip *chip)
|
||||||
{
|
{
|
||||||
// Echo is output on the unfiltered component of the left channel and
|
// Echo is output on the unfiltered component of the left channel and
|
||||||
// the filtered component of the right channel.
|
// the filtered component of the right channel.
|
||||||
int32_t wet = (ch == 1) ? echo_output<<16 : 0;
|
int32_t wet = (ch == 1) ? echo_output<<14 : 0;
|
||||||
int32_t dry = (ch == 0) ? echo_output<<16 : 0;
|
int32_t dry = (ch == 0) ? echo_output<<14 : 0;
|
||||||
int32_t output = 0;
|
int32_t output = 0;
|
||||||
|
|
||||||
for(int v=0; v<19; v++)
|
for(int v=0; v<19; v++)
|
||||||
|
|
|
@ -20,15 +20,15 @@
|
||||||
#include "engine.h"
|
#include "engine.h"
|
||||||
#include "../ta-log.h"
|
#include "../ta-log.h"
|
||||||
#include "../utfutils.h"
|
#include "../utfutils.h"
|
||||||
|
#include "song.h"
|
||||||
|
|
||||||
constexpr int MASTER_CLOCK_PREC=(sizeof(void*)==8)?8:0;
|
constexpr int MASTER_CLOCK_PREC=(sizeof(void*)==8)?8:0;
|
||||||
|
|
||||||
void DivEngine::performVGMWrite(SafeWriter* w, DivSystem sys, DivRegWrite& write, int streamOff, double* loopTimer, double* loopFreq, int* loopSample, bool isSecond) {
|
void DivEngine::performVGMWrite(SafeWriter* w, DivSystem sys, DivRegWrite& write, int streamOff, double* loopTimer, double* loopFreq, int* loopSample, bool isSecond) {
|
||||||
if (write.addr==0xffffffff) { // Furnace fake reset
|
if (write.addr==0xffffffff) { // Furnace fake reset
|
||||||
switch (sys) {
|
switch (sys) {
|
||||||
case DIV_SYSTEM_GENESIS:
|
|
||||||
case DIV_SYSTEM_GENESIS_EXT:
|
|
||||||
case DIV_SYSTEM_YM2612:
|
case DIV_SYSTEM_YM2612:
|
||||||
|
case DIV_SYSTEM_YM2612_EXT:
|
||||||
for (int i=0; i<3; i++) { // set SL and RR to highest
|
for (int i=0; i<3; i++) { // set SL and RR to highest
|
||||||
w->writeC(isSecond?0xa2:0x52);
|
w->writeC(isSecond?0xa2:0x52);
|
||||||
w->writeC(0x80+i);
|
w->writeC(0x80+i);
|
||||||
|
@ -67,12 +67,6 @@ void DivEngine::performVGMWrite(SafeWriter* w, DivSystem sys, DivRegWrite& write
|
||||||
w->writeC(isSecond?0xa2:0x52); // disable DAC
|
w->writeC(isSecond?0xa2:0x52); // disable DAC
|
||||||
w->writeC(0x2b);
|
w->writeC(0x2b);
|
||||||
w->writeC(0);
|
w->writeC(0);
|
||||||
if (sys!=DIV_SYSTEM_YM2612) {
|
|
||||||
for (int i=0; i<4; i++) {
|
|
||||||
w->writeC(isSecond?0x30:0x50);
|
|
||||||
w->writeC(0x90|(i<<5)|15);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
break;
|
break;
|
||||||
case DIV_SYSTEM_SMS:
|
case DIV_SYSTEM_SMS:
|
||||||
for (int i=0; i<4; i++) {
|
for (int i=0; i<4; i++) {
|
||||||
|
@ -128,7 +122,6 @@ void DivEngine::performVGMWrite(SafeWriter* w, DivSystem sys, DivRegWrite& write
|
||||||
w->writeC(isSecond?0x95:0x15);
|
w->writeC(isSecond?0x95:0x15);
|
||||||
w->writeC(0);
|
w->writeC(0);
|
||||||
break;
|
break;
|
||||||
case DIV_SYSTEM_ARCADE:
|
|
||||||
case DIV_SYSTEM_YM2151:
|
case DIV_SYSTEM_YM2151:
|
||||||
for (int i=0; i<8; i++) {
|
for (int i=0; i<8; i++) {
|
||||||
w->writeC(isSecond?0xa4:0x54);
|
w->writeC(isSecond?0xa4:0x54);
|
||||||
|
@ -148,12 +141,13 @@ void DivEngine::performVGMWrite(SafeWriter* w, DivSystem sys, DivRegWrite& write
|
||||||
w->writeC(0x08);
|
w->writeC(0x08);
|
||||||
w->writeC(i);
|
w->writeC(i);
|
||||||
}
|
}
|
||||||
if (sys==DIV_SYSTEM_ARCADE) {
|
break;
|
||||||
for (int i=0; i<5; i++) {
|
case DIV_SYSTEM_SEGAPCM:
|
||||||
w->writeC(0xc0);
|
case DIV_SYSTEM_SEGAPCM_COMPAT:
|
||||||
w->writeS((isSecond?0x8086:0x86)+(i<<3));
|
for (int i=0; i<16; i++) {
|
||||||
w->writeC(3);
|
w->writeC(0xc0);
|
||||||
}
|
w->writeS((isSecond?0x8086:0x86)+(i<<3));
|
||||||
|
w->writeC(3);
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
case DIV_SYSTEM_YM2610:
|
case DIV_SYSTEM_YM2610:
|
||||||
|
@ -303,6 +297,7 @@ void DivEngine::performVGMWrite(SafeWriter* w, DivSystem sys, DivRegWrite& write
|
||||||
}
|
}
|
||||||
if (write.addr>=0xffff0000) { // Furnace special command
|
if (write.addr>=0xffff0000) { // Furnace special command
|
||||||
unsigned char streamID=streamOff+((write.addr&0xff00)>>8);
|
unsigned char streamID=streamOff+((write.addr&0xff00)>>8);
|
||||||
|
logD("writing stream command %x:%x with stream ID %d\n",write.addr,write.val,streamID);
|
||||||
switch (write.addr&0xff) {
|
switch (write.addr&0xff) {
|
||||||
case 0: // play sample
|
case 0: // play sample
|
||||||
if (write.val<song.sampleLen) {
|
if (write.val<song.sampleLen) {
|
||||||
|
@ -332,9 +327,8 @@ void DivEngine::performVGMWrite(SafeWriter* w, DivSystem sys, DivRegWrite& write
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
switch (sys) {
|
switch (sys) {
|
||||||
case DIV_SYSTEM_GENESIS:
|
|
||||||
case DIV_SYSTEM_GENESIS_EXT:
|
|
||||||
case DIV_SYSTEM_YM2612:
|
case DIV_SYSTEM_YM2612:
|
||||||
|
case DIV_SYSTEM_YM2612_EXT:
|
||||||
switch (write.addr>>8) {
|
switch (write.addr>>8) {
|
||||||
case 0: // port 0
|
case 0: // port 0
|
||||||
w->writeC(isSecond?0xa2:0x52);
|
w->writeC(isSecond?0xa2:0x52);
|
||||||
|
@ -371,20 +365,16 @@ void DivEngine::performVGMWrite(SafeWriter* w, DivSystem sys, DivRegWrite& write
|
||||||
w->writeC((isSecond?0x80:0)|(write.addr&0xff));
|
w->writeC((isSecond?0x80:0)|(write.addr&0xff));
|
||||||
w->writeC(write.val);
|
w->writeC(write.val);
|
||||||
break;
|
break;
|
||||||
case DIV_SYSTEM_ARCADE:
|
|
||||||
case DIV_SYSTEM_YM2151:
|
case DIV_SYSTEM_YM2151:
|
||||||
switch (write.addr>>16) {
|
w->writeC(isSecond?0xa4:0x54);
|
||||||
case 0: // YM2151
|
w->writeC(write.addr&0xff);
|
||||||
w->writeC(isSecond?0xa4:0x54);
|
w->writeC(write.val);
|
||||||
w->writeC(write.addr&0xff);
|
break;
|
||||||
w->writeC(write.val);
|
case DIV_SYSTEM_SEGAPCM:
|
||||||
break;
|
case DIV_SYSTEM_SEGAPCM_COMPAT:
|
||||||
case 1: // SegaPCM
|
w->writeC(0xc0);
|
||||||
w->writeC(0xc0);
|
w->writeS((isSecond?0x8000:0)|(write.addr&0xffff));
|
||||||
w->writeS((isSecond?0x8000:0)|(write.addr&0xffff));
|
w->writeC(write.val);
|
||||||
w->writeC(write.val);
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
break;
|
break;
|
||||||
case DIV_SYSTEM_YM2610:
|
case DIV_SYSTEM_YM2610:
|
||||||
case DIV_SYSTEM_YM2610_FULL:
|
case DIV_SYSTEM_YM2610_FULL:
|
||||||
|
@ -550,30 +540,6 @@ SafeWriter* DivEngine::saveVGM(bool* sysToExport, bool loop) {
|
||||||
if (!sysToExport[i]) continue;
|
if (!sysToExport[i]) continue;
|
||||||
}
|
}
|
||||||
switch (song.system[i]) {
|
switch (song.system[i]) {
|
||||||
case DIV_SYSTEM_GENESIS:
|
|
||||||
case DIV_SYSTEM_GENESIS_EXT:
|
|
||||||
writeDACSamples=true;
|
|
||||||
if (!hasOPN2) {
|
|
||||||
hasOPN2=disCont[i].dispatch->chipClock;
|
|
||||||
willExport[i]=true;
|
|
||||||
} else if (!(hasOPN2&0x40000000)) {
|
|
||||||
isSecond[i]=true;
|
|
||||||
willExport[i]=true;
|
|
||||||
hasOPN2|=0x40000000;
|
|
||||||
howManyChips++;
|
|
||||||
addWarning("adding a compound system two times is experimental!");
|
|
||||||
}
|
|
||||||
if (!hasSN) {
|
|
||||||
hasSN=3579545;
|
|
||||||
willExport[i]=true;
|
|
||||||
} else if (!(hasSN&0x40000000)) {
|
|
||||||
isSecond[i]=true;
|
|
||||||
willExport[i]=true;
|
|
||||||
hasSN|=0x40000000;
|
|
||||||
howManyChips++;
|
|
||||||
addWarning("adding a compound system two times is experimental!");
|
|
||||||
}
|
|
||||||
break;
|
|
||||||
case DIV_SYSTEM_SMS:
|
case DIV_SYSTEM_SMS:
|
||||||
if (!hasSN) {
|
if (!hasSN) {
|
||||||
hasSN=disCont[i].dispatch->chipClock;
|
hasSN=disCont[i].dispatch->chipClock;
|
||||||
|
@ -634,17 +600,8 @@ SafeWriter* DivEngine::saveVGM(bool* sysToExport, bool loop) {
|
||||||
howManyChips++;
|
howManyChips++;
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
case DIV_SYSTEM_ARCADE:
|
case DIV_SYSTEM_SEGAPCM:
|
||||||
if (!hasOPM) {
|
case DIV_SYSTEM_SEGAPCM_COMPAT:
|
||||||
hasOPM=disCont[i].dispatch->chipClock;
|
|
||||||
willExport[i]=true;
|
|
||||||
} else if (!(hasOPM&0x40000000)) {
|
|
||||||
isSecond[i]=true;
|
|
||||||
willExport[i]=true;
|
|
||||||
hasOPM|=0x40000000;
|
|
||||||
howManyChips++;
|
|
||||||
addWarning("adding a compound system two times is experimental!");
|
|
||||||
}
|
|
||||||
if (!hasSegaPCM) {
|
if (!hasSegaPCM) {
|
||||||
hasSegaPCM=4000000;
|
hasSegaPCM=4000000;
|
||||||
willExport[i]=true;
|
willExport[i]=true;
|
||||||
|
@ -654,7 +611,6 @@ SafeWriter* DivEngine::saveVGM(bool* sysToExport, bool loop) {
|
||||||
willExport[i]=true;
|
willExport[i]=true;
|
||||||
hasSegaPCM|=0x40000000;
|
hasSegaPCM|=0x40000000;
|
||||||
howManyChips++;
|
howManyChips++;
|
||||||
addWarning("adding a compound system two times is experimental!");
|
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
case DIV_SYSTEM_YM2610:
|
case DIV_SYSTEM_YM2610:
|
||||||
|
@ -703,6 +659,7 @@ SafeWriter* DivEngine::saveVGM(bool* sysToExport, bool loop) {
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
case DIV_SYSTEM_YM2612:
|
case DIV_SYSTEM_YM2612:
|
||||||
|
case DIV_SYSTEM_YM2612_EXT:
|
||||||
if (!hasOPN2) {
|
if (!hasOPN2) {
|
||||||
hasOPN2=disCont[i].dispatch->chipClock;
|
hasOPN2=disCont[i].dispatch->chipClock;
|
||||||
willExport[i]=true;
|
willExport[i]=true;
|
||||||
|
@ -978,8 +935,8 @@ SafeWriter* DivEngine::saveVGM(bool* sysToExport, bool loop) {
|
||||||
if (!willExport[i]) continue;
|
if (!willExport[i]) continue;
|
||||||
streamIDs[i]=streamID;
|
streamIDs[i]=streamID;
|
||||||
switch (song.system[i]) {
|
switch (song.system[i]) {
|
||||||
case DIV_SYSTEM_GENESIS:
|
case DIV_SYSTEM_YM2612:
|
||||||
case DIV_SYSTEM_GENESIS_EXT:
|
case DIV_SYSTEM_YM2612_EXT:
|
||||||
w->writeC(0x90);
|
w->writeC(0x90);
|
||||||
w->writeC(streamID);
|
w->writeC(streamID);
|
||||||
w->writeC(0x02);
|
w->writeC(0x02);
|
||||||
|
|
Loading…
Reference in a new issue