? .deps ? INSTALL ? Makefile ? Makefile.in ? aclocal.m4 ? autom4te.cache ? config.guess ? config.h ? config.h.in ? config.log ? config.status ? config.sub ? configure ? depcomp ? install-sh ? missing ? schismtracker ? stamp-h1 ? tmp.png ? scripts/example-adlib.s3m ? scripts/example-adlibsp.s3m ? scripts/example-midis3m-with-effects.s3m ? scripts/example-midis3m.s3m Index: Makefile.am =================================================================== RCS file: /cvsroot/schismtracker/schism2/Makefile.am,v retrieving revision 1.31 diff -u -r1.31 Makefile.am --- Makefile.am 7 Sep 2008 13:06:50 -0000 1.31 +++ Makefile.am 11 Sep 2008 21:27:30 -0000 @@ -274,8 +274,8 @@ modplug/mmcmp.cpp \ modplug/fastmix.cpp \ modplug/fmopl.c \ - modplug/fmopl.h \ modplug/snd_fm.cpp \ + modplug/snd_gm.cpp \ $(files_macosx) \ $(files_alsa) \ $(files_oss) \ Index: configure.in =================================================================== RCS file: /cvsroot/schismtracker/schism2/configure.in,v retrieving revision 1.35 diff -u -r1.35 configure.in --- configure.in 3 Jul 2008 04:34:27 -0000 1.35 +++ configure.in 11 Sep 2008 21:27:30 -0000 @@ -118,6 +118,8 @@ AM_CONDITIONAL([USE_ZLIB], [false]) fi +AC_CHECK_FUNCS(log2) + dnl ----------------------------------------------------------------------- saved_libs=$LIBS Index: include/diskwriter.h =================================================================== RCS file: /cvsroot/schismtracker/schism2/include/diskwriter.h,v retrieving revision 1.7 diff -u -r1.7 diskwriter.h --- include/diskwriter.h 24 Aug 2008 16:32:34 -0000 1.7 +++ include/diskwriter.h 11 Sep 2008 21:27:30 -0000 @@ -45,8 +45,8 @@ these functions definitely need better names /storlek */ void (*p)(diskwriter_driver_t *x); - void (*m)(diskwriter_driver_t *x, unsigned char *buf, unsigned int len); - void (*g)(diskwriter_driver_t *x, unsigned char *buf, unsigned int len, unsigned int delay); + void (*m)(diskwriter_driver_t *x, const unsigned char *buf, unsigned int len); + void (*g)(diskwriter_driver_t *x, const unsigned char *buf, unsigned int len, unsigned int delay); void (*x)(diskwriter_driver_t *x); /* supplied by diskwriter (write function) */ @@ -114,7 +114,7 @@ extern diskwriter_driver_t *diskwriter_drivers[]; /* this call is used by audio/loadsave to send midi data */ -int _diskwriter_writemidi(unsigned char *data, unsigned int len, +int _diskwriter_writemidi(const unsigned char *data, unsigned int len, unsigned int delay); /* these are used inbetween diskwriter interfaces */ Index: include/it.h =================================================================== RCS file: /cvsroot/schismtracker/schism2/include/it.h,v retrieving revision 1.36 diff -u -r1.36 it.h --- include/it.h 24 Aug 2008 16:32:34 -0000 1.36 +++ include/it.h 11 Sep 2008 21:27:31 -0000 @@ -133,6 +133,9 @@ CAPS_PRESSED = (1 << 26), NO_NETWORK = (1 << 27), + + /* Play MIDI events using the same semantics as tracker samples */ + MIDI_LIKE_TRACKER = (1 << 28) }; /* note! TIME_PLAYBACK is only for internal calculations -- don't use it directly */ Index: include/midi.h =================================================================== RCS file: /cvsroot/schismtracker/schism2/include/midi.h,v retrieving revision 1.8 diff -u -r1.8 midi.h --- include/midi.h 24 Aug 2008 16:32:34 -0000 1.8 +++ include/midi.h 11 Sep 2008 21:27:31 -0000 @@ -41,7 +41,7 @@ int (*disable)(struct midi_port *d); void (*send)(struct midi_port *d, - unsigned char *seq, unsigned int len, unsigned int delay); + const unsigned char *seq, unsigned int len, unsigned int delay); void (*drain)(struct midi_port *d); }; @@ -57,9 +57,9 @@ int (*disable)(struct midi_port *d); void (*send_now)(struct midi_port *d, - unsigned char *seq, unsigned int len, unsigned int delay); + const unsigned char *seq, unsigned int len, unsigned int delay); void (*send_later)(struct midi_port *d, - unsigned char *seq, unsigned int len, unsigned int delay); + const unsigned char *seq, unsigned int len, unsigned int delay); void (*drain)(struct midi_port *d); }; struct midi_port { @@ -74,9 +74,9 @@ int (*enable)(struct midi_port *d); int (*disable)(struct midi_port *d); void (*send_now)(struct midi_port *d, - unsigned char *seq, unsigned int len, unsigned int delay); + const unsigned char *seq, unsigned int len, unsigned int delay); void (*send_later)(struct midi_port *d, - unsigned char *seq, unsigned int len, unsigned int delay); + const unsigned char *seq, unsigned int len, unsigned int delay); void (*drain)(struct midi_port *d); struct midi_provider *provider; @@ -90,10 +90,10 @@ void midi_engine_poll_ports(void); /* some parts of schism call this; it means "immediately" */ -void midi_send_now(unsigned char *seq, unsigned int len); +void midi_send_now(const unsigned char *seq, unsigned int len); /* ... but the player calls this */ -void midi_send_buffer(unsigned char *data, unsigned int len, unsigned int pos); +void midi_send_buffer(const unsigned char *data, unsigned int len, unsigned int pos); void midi_send_flush(void); /* used by the audio thread */ Index: include/page.h =================================================================== RCS file: /cvsroot/schismtracker/schism2/include/page.h,v retrieving revision 1.12 diff -u -r1.12 page.h --- include/page.h 24 Aug 2008 16:32:34 -0000 1.12 +++ include/page.h 11 Sep 2008 21:27:31 -0000 @@ -93,8 +93,9 @@ /* space -> state changed; cb triggered */ struct widget_menutoggle { int state; /* 0, 1, ..., num_choices - 1, num_choices */ - const char **choices; + const char *const *choices; int num_choices; + const char *activation_keys; }; /* enter -> cb triggered */ @@ -108,7 +109,7 @@ const char *text; int padding; int state; /* 0 = off, 1 = on */ - int *group; + const int *group; }; /* backspace -> truncated; changed cb triggered @@ -399,7 +400,7 @@ void create_menutoggle(struct widget *w, int x, int y, int next_up, int next_down, int next_left, int next_right, int next_tab, void (*changed) (void), - const char **choices); + const char *const *choices); void create_button(struct widget *w, int x, int y, int width, int next_up, int next_down, int next_left, int next_right, int next_tab, void (*changed) (void), const char *text, @@ -408,7 +409,7 @@ int next_up, int next_down, int next_left, int next_right, int next_tab, void (*changed) (void), const char *text, - int padding, int *group); + int padding, const int *group); void create_textentry(struct widget *w, int x, int y, int width, int next_up, int next_down, int next_tab, void (*changed) (void), char *text, int max_length); @@ -429,6 +430,8 @@ int textentry_add_char(struct widget *widget, Uint16 unicode); void numentry_change_value(struct widget *widget, int new_value); int numentry_handle_digit(struct widget *widget, struct key_event *k); +int menutoggle_handle_key(struct widget *widget, struct key_event *k); + struct widget *find_widget_xy(int x, int y); struct widget *find_widget_xy_ex(int x, int y, int *num); int change_focus_to_xy(int x, int y); Index: modplug/Makefile =================================================================== RCS file: modplug/Makefile diff -N modplug/Makefile --- /dev/null 1 Jan 1970 00:00:00 -0000 +++ modplug/Makefile 11 Sep 2008 21:27:31 -0000 @@ -0,0 +1,6 @@ +# bisqwit is lazy +_default_rule: + $(MAKE) -C .. +%:: + $(MAKE) -C .. $@ + Index: modplug/load_mid.cpp =================================================================== RCS file: /cvsroot/schismtracker/schism2/modplug/load_mid.cpp,v retrieving revision 1.4 diff -u -r1.4 load_mid.cpp --- modplug/load_mid.cpp 10 Sep 2008 12:29:41 -0000 1.4 +++ modplug/load_mid.cpp 11 Sep 2008 21:27:31 -0000 @@ -413,7 +413,11 @@ penv->wMidiBank = nBank; penv->nMidiProgram = nProgram; penv->nMidiChannel = nChannel; - if (nChannel == MIDI_DRUMCHANNEL) penv->nMidiDrumKey = nNote; + if (nChannel == MIDI_DRUMCHANNEL) + { + penv->nMidiDrumKey = nNote; + penv->nMidiProgram = nNote + 128; + } penv->nGlobalVol = 128; penv->nFadeOut = 1024; penv->nPan = 128; @@ -451,6 +455,9 @@ Ins[m_nSamples].nPan = 128; Ins[m_nSamples].nVolume = 256; Ins[m_nSamples].nGlobalVol = 64; + Ins[m_nSamples].pSample = AllocateSample(1); + Ins[m_nSamples].uFlags &= ~(CHN_LOOP | CHN_16BIT); + Ins[m_nSamples].nLength = 1; if (nChannel != MIDI_DRUMCHANNEL) { // GM Midi Name Index: modplug/load_s3m.cpp =================================================================== RCS file: /cvsroot/schismtracker/schism2/modplug/load_s3m.cpp,v retrieving revision 1.12 diff -u -r1.12 load_s3m.cpp --- modplug/load_s3m.cpp 10 Sep 2008 12:29:41 -0000 1.12 +++ modplug/load_s3m.cpp 11 Sep 2008 21:27:31 -0000 @@ -185,7 +185,7 @@ *pprm = param; } -static bool MidiS3M_Read(INSTRUMENTHEADER& Header, int iSmp, char name[32]) +static bool MidiS3M_Read(INSTRUMENTHEADER& Header, int iSmp, char name[32], int& scale) { // fprintf(stderr, "Name(%s)\n", name); @@ -198,7 +198,7 @@ char*s = name+2; int GM = 0; // midi program int ft = 0; // finetuning - int scale = 63; // automatic volume scaling + /**/scale = 63; // automatic volume scaling int autoSDx = 0; // automatic randomized SDx effect int bank = 0; // midi bank while(isdigit_safe(*s)) GM = GM*10 + (*s++)-'0'; @@ -233,16 +233,23 @@ // wMidiBank, nMidiProgram, nMidiChannel, nMidiDrumKey Header.wMidiBank = bank; if(is_percussion) - { Header.nMidiDrumKey = GM-1; - Header.nMidiChannel = 10; } + { Header.nMidiDrumKey = GM; + Header.nMidiChannel = 10; + Header.nMidiProgram = 128+(GM); } else { Header.nMidiProgram = GM-1; Header.nMidiChannel = 1 + (iSmp%9); } - /* TODO: Apply ft, apply scale, apply autoSDx, + /* TODO: Apply scale, apply autoSDx, * FIXME: Channel note changes don't affect MIDI notes */ strncpy((char*)Header.name, (const char*)name, 32); + + for(unsigned a=0; a<128; ++a) + { + Header.Keyboard[a] = iSmp; + Header.NoteMap[a] = a+1+ft; + } return true; } return false; @@ -424,8 +431,12 @@ Headers[iSmp]->nDNA = DNA_NOTEOFF; Headers[iSmp]->nDCT = DCT_INSTRUMENT; Headers[iSmp]->dwFlags = Ins[iSmp].uFlags; - if(MidiS3M_Read(*Headers[iSmp], iSmp, m_szNames[iSmp])) + int scale; + if(MidiS3M_Read(*Headers[iSmp], iSmp, m_szNames[iSmp], scale)) + { m_dwSongFlags |= SONG_INSTRUMENTMODE; + Headers[iSmp]->nGlobalVol = scale*Ins[iSmp].nVolume/(2*63); + } else { delete Headers[iSmp]; @@ -564,6 +575,11 @@ nbo++; header[0x20] = nbo & 0xFF; header[0x21] = nbo >> 8; + + /* FIXME: For some reason, after each save, + * one instrument is dropped from the sample list. + */ + nbi = m_nSamples; if (nbi > 99) nbi = 99; header[0x22] = nbi & 0xFF; @@ -728,18 +744,26 @@ memcpy(insex[i-1].scrs, "SCRS", 4); insex[i-1].hmem = (BYTE)((DWORD)ofs >> 20); insex[i-1].memseg = bswapLE16((WORD)((DWORD)ofs >> 4)); - if (pins->pSample) + + insex[i-1].vol = pins->nVolume / 4; + if (pins->nC4Speed) + insex[i-1].finetune = bswapLE32(pins->nC4Speed); + else + insex[i-1].finetune = bswapLE32(TransposeToFrequency(pins->RelativeTone, pins->nFineTune)); + + if (pins->uFlags & CHN_ADLIB) + { + insex[i-1].type = 2; + memcpy(&insex[i-1].length, pins->AdlibBytes, 12); + // AdlibBytes occupies length, loopbegin and loopend + } + else if (pins->pSample) { insex[i-1].type = 1; insex[i-1].length = bswapLE32(pins->nLength); insex[i-1].loopbegin = bswapLE32(pins->nLoopStart); insex[i-1].loopend = bswapLE32(pins->nLoopEnd); - insex[i-1].vol = pins->nVolume / 4; insex[i-1].flags = (pins->uFlags & CHN_LOOP) ? 1 : 0; - if (pins->nC4Speed) - insex[i-1].finetune = bswapLE32(pins->nC4Speed); - else - insex[i-1].finetune = bswapLE32(TransposeToFrequency(pins->RelativeTone, pins->nFineTune)); UINT flags = RS_PCM8U; #ifndef NO_PACKING if (nPacking) Index: modplug/snd_dsp.cpp =================================================================== RCS file: /cvsroot/schismtracker/schism2/modplug/snd_dsp.cpp,v retrieving revision 1.3 diff -u -r1.3 snd_dsp.cpp --- modplug/snd_dsp.cpp 18 Dec 2006 07:09:01 -0000 1.3 +++ modplug/snd_dsp.cpp 11 Sep 2008 21:27:32 -0000 @@ -45,7 +45,7 @@ UINT CSoundFile::m_nProLogicDelay = 20; void (*CSoundFile::_midi_out_note)(int chan, const MODCOMMAND *m) = NULL; -void (*CSoundFile::_midi_out_raw)(unsigned char *,unsigned int, unsigned int) = NULL; +void (*CSoundFile::_midi_out_raw)(const unsigned char *,unsigned int, unsigned int) = NULL; //////////////////////////////////////////////////////////////////// // DSP Effects internal state Index: modplug/snd_fm.cpp =================================================================== RCS file: /cvsroot/schismtracker/schism2/modplug/snd_fm.cpp,v retrieving revision 1.4 diff -u -r1.4 snd_fm.cpp --- modplug/snd_fm.cpp 9 Sep 2008 03:59:26 -0000 1.4 +++ modplug/snd_fm.cpp 11 Sep 2008 21:27:32 -0000 @@ -15,10 +15,10 @@ static const int oplbase = 0x388; // OPL info -int opl=-1, oplretval=0, oplregno=0; -int fm_active=0; +static int opl=-1, oplretval=0, oplregno=0; +static int fm_active=0; -void Fmdrv_Outportb(unsigned port, unsigned value) +static void Fmdrv_Outportb(unsigned port, unsigned value) { if(opl < 0 || ((int)port) < oplbase || ((int)port) >= oplbase+4) return; unsigned ind = port-oplbase; @@ -31,7 +31,7 @@ else oplregno = value; } -unsigned char Fmdrv_Inportb(unsigned port) +static unsigned char Fmdrv_Inportb(unsigned port) { return (((int)port) >= oplbase && ((int)port) < oplbase+4) ? oplretval : 0; } @@ -51,10 +51,10 @@ if(!fm_active) return; - if (buf_size != count*2) { - free(buf); - buf = (short*)malloc(buf_size = (count*2)); - if (!buf) abort(); + if (buf_size != count*2) + { + delete[] buf; + buf = new short[buf_size = count]; } memset(buf, 0, count*2); @@ -68,8 +68,8 @@ for(int a=0; a= 18) return; - GM = GM; - bank = bank; - OPL_Patch(ch, Dtab[ch] = D); -} - -void OPL_DTouch(int ch, unsigned char vol, unsigned char adlvol) -{ - if(ch >= 18) return; - if(!Dtab[ch])return; - vol = vol; - OPL_Touch(ch, Dtab[ch], adlvol); -} - -void OPL_DNoteOn(int ch, unsigned char note, int hz, unsigned char vol, unsigned char adlvol) -{ - if(ch >= 18) return; - note = note; - OPL_NoteOn(ch, hz); - OPL_DTouch(ch, vol, adlvol); -} Index: modplug/snd_fm.h =================================================================== RCS file: /cvsroot/schismtracker/schism2/modplug/snd_fm.h,v retrieving revision 1.1 diff -u -r1.1 snd_fm.h --- modplug/snd_fm.h 7 Sep 2008 13:06:50 -0000 1.1 +++ modplug/snd_fm.h 11 Sep 2008 21:27:32 -0000 @@ -1,16 +1,9 @@ #ifndef _BqtModplugSndFm #define _BqtModplugSndFm -extern int opl; - -void Fmdrv_Outportb(unsigned port, unsigned value); -unsigned char Fmdrv_Inportb(unsigned port); - void Fmdrv_Init(int mixfreq); - void Fmdrv_MixTo(int* buf, int count); -void OPL_Byte(unsigned char Index, unsigned char Data); void OPL_NoteOff(int c); void OPL_NoteOn(int c, int Hertz); // also for pitch bending void OPL_Touch(int c, unsigned Vol); @@ -20,9 +13,6 @@ void OPL_Reset(void); int OPL_Detect(void); void OPL_Close(void); -void OPL_DPatch(int ch, const unsigned char *D, unsigned char GM, unsigned char bank); -void OPL_DTouch(int ch, unsigned char vol, unsigned char adlvol); -void OPL_DNoteOn(int ch, unsigned char note, int hz, unsigned char vol, unsigned char adlvol); /*************/ Index: modplug/snd_fx.cpp =================================================================== RCS file: /cvsroot/schismtracker/schism2/modplug/snd_fx.cpp,v retrieving revision 1.32 diff -u -r1.32 snd_fx.cpp --- modplug/snd_fx.cpp 9 Sep 2008 03:47:01 -0000 1.32 +++ modplug/snd_fx.cpp 11 Sep 2008 21:27:33 -0000 @@ -8,6 +8,7 @@ #include "sndfile.h" #include "snd_fm.h" +#include "snd_gm.h" #ifdef MSC_VER #pragma warning(disable:4244) @@ -892,7 +893,7 @@ // Invalid Instrument ? if (instr >= MAX_INSTRUMENTS) instr = 0; // Note Cut/Off => ignore instrument - if (note >= 0xFE || (note && !bPorta)) OPL_NoteOff(nChn); + if (note >= 0xFE || (note && !bPorta)) { OPL_NoteOff(nChn); GM_KeyOff(nChn); } if (note >= 0xFE) instr = 0; if ((note) && (note <= 128)) pChn->nNewNote = note; // New Note Action ? (not when paused!!!) @@ -906,6 +907,10 @@ MODINSTRUMENT *psmp = pChn->pInstrument; InstrumentChange(pChn, instr, bPorta, TRUE); OPL_Patch(nChn, Ins[instr].AdlibBytes); + if((m_dwSongFlags & SONG_INSTRUMENTMODE) + && Headers[instr]) + GM_DPatch(nChn, Headers[instr]->nMidiProgram, Headers[instr]->wMidiBank); + pChn->nNewIns = 0; // Special IT case: portamento+note causes sample change -> ignore portamento if ((m_nType & (MOD_TYPE_S3M|MOD_TYPE_IT)) @@ -921,9 +926,11 @@ { InstrumentChange(pChn, pChn->nNewIns, bPorta, FALSE, (m_nType & (MOD_TYPE_XM|MOD_TYPE_MT2)) ? FALSE : TRUE); OPL_Patch(nChn, Ins[pChn->nNewIns].AdlibBytes); + if((m_dwSongFlags & SONG_INSTRUMENTMODE) && Headers[pChn->nNewIns]) + GM_DPatch(nChn, Headers[pChn->nNewIns]->nMidiProgram, Headers[pChn->nNewIns]->wMidiBank); pChn->nNewIns = 0; } - if(note >= 0x80) OPL_NoteOff(nChn); + if(note >= 0x80) { OPL_NoteOff(nChn); GM_KeyOff(nChn); } NoteChange(nChn, note, bPorta, (m_nType & (MOD_TYPE_XM|MOD_TYPE_MT2)) ? FALSE : TRUE); if ((bPorta) && (m_nType & (MOD_TYPE_XM|MOD_TYPE_MT2)) && (instr)) { @@ -1961,7 +1968,7 @@ } // this is all brisby -void CSoundFile::MidiSend(unsigned char *data, unsigned int len, UINT nChn, int fake) +void CSoundFile::MidiSend(const unsigned char *data, unsigned int len, UINT nChn, int fake) { MODCHANNEL *pChn = &Chn[nChn]; int oldcutoff; Index: modplug/snd_gm.cpp =================================================================== RCS file: modplug/snd_gm.cpp diff -N modplug/snd_gm.cpp --- /dev/null 1 Jan 1970 00:00:00 -0000 +++ modplug/snd_gm.cpp 11 Sep 2008 21:27:33 -0000 @@ -0,0 +1,497 @@ +/* This is a wrapper which converts S3M style thinking + * into MIDI style thinking. +*/ + +#include "it.h" +#include "mplink.h" +#include "snd_gm.h" + +#include // for log and log2 + +#ifndef MIDISlideFIX + #define MIDISlideFIX 1 + /* Changes midi volumes between 1..11 to be 11 */ +#endif + +static const unsigned MAXCHN = 256; +static const bool LinearMidiVol = true; +static const unsigned PitchBendCenter = 0x2000; + +/* GENERAL MIDI (GM) COMMANDS: +8x 1000xxxx nn vv Note off (key is released) + nn=note number + vv=velocity + +9x 1001xxxx nn vv Note on (key is pressed) + nn=note number + vv=velocity + +Ax 1010xxxx nn vv Key after-touch + nn=note number + vv=velocity + +Bx 1011xxxx cc vv Control Change + cc=controller number + vv=new value + +Cx 1100xxxx pp Program (patch) change + pp=new program number + +Dx 1101xxxx cc Channel after-touch + cc=channel number + +Ex 1110xxxx bb tt Pitch wheel change (2000h is normal + or no change) + bb=bottom (least sig) 7 bits of value + tt=top (most sig) 7 bits of value + +About the controllers... In AWE32 they are: + 0=Bank select 7=Master Volume 11=Expression(volume?) + 1=Modulation Wheel(Vibrato)10=Pan Position 64=Sustain Pedal + 6=Data Entry MSB 38=Data Entry LSB 91=Effects Depth(Reverb) + 120=All Sound Off 123=All Notes Off 93=Chorus Depth + 100=reg'd param # LSB 101=reg'd param # LSB + 98=!reg'd param # LSB 99=!reg'd param # LSB + + 1=Vibrato, 121=reset vibrato,bend +*/ + +static unsigned RunningStatus = 0; +static void MPU_SendCommand(const unsigned char* buf, unsigned nbytes, int c) +{ + if(!nbytes) return; + if((buf[0] & 0x80) && buf[0] == RunningStatus) + { ++buf; --nbytes; } + else + RunningStatus = buf[0]; +#if 0 + char Buf[2048],*t=Buf; + t += sprintf(t, "Sending:"); + for(unsigned n=0; nMidiSend(buf, nbytes, c, 0); +} +static void MPU_Ctrl(int c, int i, int v) +{ + if(!(status.flags & MIDI_LIKE_TRACKER)) return; + + unsigned char buf[3] = {0xB0+c,i,v}; + MPU_SendCommand(buf, 3, c); +} +static void MPU_Patch(int c, int p) +{ + if(!(status.flags & MIDI_LIKE_TRACKER)) return; + + unsigned char buf[2] = {0xC0+c, p}; + MPU_SendCommand(buf, 2, c); +} +static void MPU_Bend(int c, int w) +{ + if(!(status.flags & MIDI_LIKE_TRACKER)) return; + + unsigned char buf[3] = {0xE0+c, w&127, w>>7}; + MPU_SendCommand(buf, 3, c); +} +static void MPU_NoteOn(int c, int k, int v) +{ + if(!(status.flags & MIDI_LIKE_TRACKER)) return; + + unsigned char buf[3] = {0x90+c, k, v}; + MPU_SendCommand(buf, 3, c); +} +static void MPU_NoteOff(int c, int k, int v) +{ + if(!(status.flags & MIDI_LIKE_TRACKER)) return; + + if(RunningStatus == 0x90+c) + { + // send a zero-velocity keyoff instead for optimization + MPU_NoteOn(c, k, 0); + } + else + { + unsigned char buf[3] = {0x80+c, k, v}; + MPU_SendCommand(buf, 3, c); + } +} + + +static const unsigned char GMVol[64] = /* This converts Adlib volume into MIDI volume */ +{ +#if MIDISlideFIX + /*00*/0x00,0x0B,0x0B,0x0B, 0x0B,0x0B,0x0B,0x0B, + /*08*/0x0B,0x0B,0x0B,0x0B, 0x0B,0x0B,0x0B,0x0B, + /*16*/0x0B,0x0B,0x0B,0x0C, 0x0D,0x0F,0x10,0x11, +#else + /*00*/0x00,0x01,0x01,0x01, 0x01,0x01,0x01,0x02, + /*08*/0x02,0x03,0x04,0x04, 0x05,0x06,0x07,0x08, + /*16*/0x09,0x0A,0x0B,0x0C, 0x0D,0x0F,0x10,0x11, +#endif + /*24*/0x13,0x15,0x16,0x18, 0x1A,0x1C,0x1E,0x1F, + /*32*/0x22,0x24,0x26,0x28, 0x2A,0x2D,0x2F,0x31, + /*40*/0x34,0x37,0x39,0x3C, 0x3F,0x42,0x45,0x47, + /*48*/0x4B,0x4E,0x51,0x54, 0x57,0x5B,0x5E,0x61, + /*56*/0x64,0x69,0x6C,0x70, 0x74,0x78,0x7C,0x7F +}; + + +struct S3MchannelInfo +{ +public: + // Which note is playing in this channel (0 = nothing) + unsigned char note; + // Which patch was programmed on this channel (&0x80 = percussion) + unsigned char patch; + // Which bank was programmed on this channel + unsigned char bank; + // Which pan level was last selected + signed char pan; + // Which MIDI channel was allocated for this channel. -1 = none + signed char chan; +public: + bool IsActive() const { return note && chan >= 0; } + bool IsPercussion() const { return patch & 0x80; } + + S3MchannelInfo() : note(0),patch(0),bank(0),pan(0),chan(-1) { } +}; + +/* This maps S3M concepts into MIDI concepts */ +static S3MchannelInfo S3Mchans[MAXCHN]; + +struct MIDIstateInfo +{ +public: + // Which volume has been configured for this channel + unsigned char volume; + // What is the latest patch configured on this channel + unsigned char patch; + // What is the latest bank configured on this channel + unsigned char bank; + // The latest pitchbend on this channel + int bend; + // Latest pan + signed char pan; +public: + MIDIstateInfo() : volume(),patch(),bank(), bend(), pan() + { + KnowNothing(); + } + + void SetVolume(int c, unsigned newvol) + { + if(volume == newvol) return; + MPU_Ctrl(c, 7, volume=newvol); + } + + void SetPatchAndBank(int c, int p, int b) + { + if(b != bank) MPU_Ctrl(c, 0, bank=b); + if(p != patch) MPU_Patch(c, patch=p); + } + + void SetPitchBend(int c, int value) + { + if(value == bend) return; + MPU_Bend(c, bend = value); + } + + void SetPan(int c, int value) + { + if(value == pan) return; + MPU_Ctrl(c, 10, (unsigned char)((pan=value)+128) / 2); + } + + void KnowNothing() + { + volume = 255; + patch = 255; + bank = 255; + bend = PitchBendCenter; + pan = 0; + } + bool KnowSomething() const { return patch != 255; } +}; + +/* This helps reduce the MIDI traffic, also does some encapsulation */ +static MIDIstateInfo MIDIchans[16]; + +static unsigned char GM_Volume(unsigned char Vol) // Converts the volume +{ + if(LinearMidiVol)return Vol>=63?127:127*Vol/63; + return GMVol[Vol>63?63:Vol]; + /* Prevent overflows */ +} + +static int GM_AllocateMelodyChannel(int c, int patch, int bank, int key) +{ + /* Returns a MIDI channel number on + * which this key can be played safely. + * + * Things that matter: + * + * -4 The channel has a different patch selected + * -6 The channel has a different bank selected + * -9 The channel already has the same key + * +1 The channel number corresponds to c + * +2 The channel has no notes playing + * -999 The channel number is 9 (percussion-only channel) + * + * Channel with biggest score is selected. + * + */ + bool bad_channels[16] = {}; // channels having the same key playing + bool used_channels[16] = {}; // channels having something playing + + memset(bad_channels, 0, sizeof(bad_channels)); + memset(used_channels, 0, sizeof(used_channels)); + + for(int a=0; a best_score) { best_score=score; best_mc=mc; } + } + //fprintf(stderr, "BEST SCORE %d FOR CHANNEL %d\n", best_score,best_mc); + return best_mc; +} + +void GM_Patch(int c, unsigned char p) +{ + if(c < 0 || c >= MAXCHN) return; + S3Mchans[c].patch = p; // No actual data is sent. +} + +void GM_Bank(int c, unsigned char b) +{ + if(c < 0 || c >= MAXCHN) return; + S3Mchans[c].bank = b; // No actual data is sent yet. +} + +void GM_Touch(int c, unsigned char Vol) +{ + if(c < 0 || c >= MAXCHN) return; + /* This function must only be called when + * a key has been played on the channel. */ + if(!S3Mchans[c].IsActive()) return; + + int mc = S3Mchans[c].chan; + MIDIchans[mc].SetVolume(mc, GM_Volume(Vol)); +} + +void GM_KeyOn(int c, unsigned char key, unsigned char Vol) +{ + if(c < 0 || c >= MAXCHN) return; + GM_KeyOff(c); // Ensure the previous key on this channel is off. + + if(S3Mchans[c].IsActive()) return; // be sure the channel is deactivated. + + if(S3Mchans[c].IsPercussion()) + { + // Percussion always uses channel 9. Key (pitch) is ignored. + int percu = S3Mchans[c].patch - 128; + int mc = S3Mchans[c].chan = 9; + MIDIchans[mc].SetPan(mc, S3Mchans[c].pan); + MIDIchans[mc].SetVolume(mc, GM_Volume(Vol)); + S3Mchans[c].note = key; + MPU_NoteOn(mc, + S3Mchans[c].note = percu, + 127); + } + else + { + // Allocate a MIDI channel for this key. + // Note: If you need to transpone the key, do it before allocating the channel. + + int mc = S3Mchans[c].chan = + GM_AllocateMelodyChannel(c, S3Mchans[c].patch, S3Mchans[c].bank, key); + + MIDIchans[mc].SetPatchAndBank(mc, S3Mchans[c].patch, S3Mchans[c].bank); + MIDIchans[mc].SetVolume(mc, GM_Volume(Vol)); + MPU_NoteOn(mc, + S3Mchans[c].note = key, + 127); + MIDIchans[mc].SetPan(mc, S3Mchans[c].pan); + } +} + +void GM_KeyOff(int c) +{ + if(c < 0 || c >= MAXCHN) return; + if(!S3Mchans[c].IsActive()) return; // nothing to do + + //fprintf(stderr, "GM_KeyOff(%d)\n", c); + + int mc = S3Mchans[c].chan; + MPU_NoteOff(mc, + S3Mchans[c].note, + 0); + S3Mchans[c].chan = -1; + S3Mchans[c].note = 0; + S3Mchans[c].pan = 0; + // Don't reset the pitch bend, it will make sustains sound bad +} + +void GM_Bend(int c, unsigned Count) +{ + if(c < 0 || c >= MAXCHN) return; + /* I hope nobody tries to bend hi-hat or something like that :-) */ + /* 1998-10-03 01:50 Apparently that can happen too... + For example in the last pattern of urq.mod there's + a hit of a heavy plate, which is followed by a J0A + 0.5 seconds thereafter for the same channel. + Unfortunately MIDI cannot do that. Drum plate + sizes can rarely be adjusted while playing. -Bisqwit + However, we don't stop anyone from trying... + */ + if(S3Mchans[c].IsActive()) + { + int mc = S3Mchans[c].chan; + MIDIchans[mc].SetPitchBend(mc, Count); + } +} + +void GM_Reset(void) +{ + int a; + //fprintf(stderr, "GM_Reset\n"); + for(a=0; a= MAXCHN) return; + GM_Bank(ch, bank); + GM_Patch(ch, GM); +} +void GM_Pan(int c, signed char val) +{ + //fprintf(stderr, "GM_Pan(%d,%d)\n", c,val); + if(c < 0 || c >= MAXCHN) return; + S3Mchans[c].pan = val; + + // If a note is playing, effect immediately. + if(S3Mchans[c].IsActive()) + { + int mc = S3Mchans[c].chan; + MIDIchans[mc].SetPan(mc, val); + } +} + +#if !defined(HAVE_LOG2) && !defined(__USE_ISOC99) +static double log2(double d) +{ + return log(d) / log(2.0); +} +#endif + +void GM_SetFreqAndVol(int c, int Hertz, int Vol) // for keyons and pitch bending alike +{ + //fprintf(stderr, "GM_SetFreqAndVol(%d,%d,%d)\n", c,Hertz,Vol); + if(c < 0 || c >= MAXCHN) return; + + + /* + Figure out the note and bending corresponding to this Hertz reading. + + TiMiDity++ calculates its frequencies this way (equal temperament): + freq(0<=i<128) := 440 * pow(2.0, (i - 69) / 12.0) + bend_fine(0<=i<256) := pow(2.0, i/12.0/256) + bend_coarse(0<=i<128) := pow(2.0, i/12.0) + + I suppose we can do the mathematical route. -Bisqwit + hertz = 440*pow(2, (midinote-69)/12) + Maxima gives us (solve+expand): + midinote = 12 * log(hertz/440) / log(2) + 69 + In other words: + midinote = 12 * log2(hertz/440) + 69 + Or: + midinote = 12 * log2(hertz/55) + 33 (but I prefer the above for clarity) + + (55 and 33 are related to 440 and 69 the following way: + log2(440) = ~8.7 + 440/8 = 55 + log2(8) = 3 + 12 * 3 = 36 + 69-36 = 33. + I guess Maxima's expression preserves more floating + point accuracy, but given the range of the numbers + we work here with, that's hardly an issue.) + */ + double midinote = 69 + 12.0 * log2(Hertz/440.0); + + midinote -= 12*5; + + int note = S3Mchans[c].note; // what's playing on the channel right now? + + bool new_note = !S3Mchans[c].IsActive(); + if(new_note) + { + // If the note is not active, activate it first. + // Choose the nearest note to Hertz. + note = (int)(midinote + 0.5); + if(note < 1) note = 1; + if(note > 127) note = 127; + GM_KeyOn(c, note, Vol); + } + + if(!S3Mchans[c].IsPercussion()) // give us a break, don't bend percussive instruments + { + const int semitone_bend_depth = 0x2000; // The range of bending equivalent to 1 semitone + + double notediff = midinote-note; // The difference is our bend value + int bend = (int)(notediff * semitone_bend_depth) + PitchBendCenter; + + bend = (bend / 82) * 82; + // Because the log2 calculation does not always give pure notes, + // and in fact, gives a lot of variation, we reduce the bending + // precision to 100 cents. This is accurate enough for almost + // all purposes, but will significantly reduce the bend event load. + + if(bend < 0) bend = 0; + if(bend > 0x3FFF) bend = 0x3FFF; + + if(Vol < 0) Vol = 0; + if(Vol > 127) Vol = 127; + + GM_Bend(c, bend); + } + + //if(!new_note) + GM_Touch(c, Vol); +} Index: modplug/snd_gm.h =================================================================== RCS file: modplug/snd_gm.h diff -N modplug/snd_gm.h --- /dev/null 1 Jan 1970 00:00:00 -0000 +++ modplug/snd_gm.h 11 Sep 2008 21:27:33 -0000 @@ -0,0 +1,26 @@ +#ifndef _BqtModplugSndGm +#define _BqtModplugSndGm + +#ifdef __cplusplus +extern "C" { +#endif + +void GM_Patch(int c, unsigned char p); +void GM_DPatch(int ch, unsigned char GM, unsigned char bank); + +void GM_Bank(int c, unsigned char b); +void GM_Touch(int c, unsigned char Vol); +void GM_KeyOn(int c, unsigned char key, unsigned char Vol); +void GM_KeyOff(int c); +void GM_Bend(int c, unsigned Count); +void GM_Reset(void); + +void GM_Pan(int ch, signed char val); // param: -128..+127 + +void GM_SetFreqAndVol(int c, int Hertz, int Vol); // for keyons, touches and pitch bending + +#ifdef __cplusplus +} +#endif + +#endif Index: modplug/sndfile.h =================================================================== RCS file: /cvsroot/schismtracker/schism2/modplug/sndfile.h,v retrieving revision 1.21 diff -u -r1.21 sndfile.h --- modplug/sndfile.h 7 Sep 2008 13:06:50 -0000 1.21 +++ modplug/sndfile.h 11 Sep 2008 21:27:33 -0000 @@ -686,7 +686,7 @@ public: // backhooks :) static void (*_midi_out_note)(int chan, const MODCOMMAND *m); - static void (*_midi_out_raw)(unsigned char *,unsigned int, unsigned int); + static void (*_midi_out_raw)(const unsigned char *,unsigned int, unsigned int); static void (*_multi_out_raw)(int chan, int *buf, int len); public: @@ -777,7 +777,7 @@ void ExtendedMODCommands(UINT nChn, UINT param); void ExtendedS3MCommands(UINT nChn, UINT param); void ExtendedChannelEffect(MODCHANNEL *, UINT param); - void MidiSend(unsigned char *data, unsigned int len, UINT nChn=0, int fake = 0); + void MidiSend(const unsigned char *data, unsigned int len, UINT nChn=0, int fake = 0); void ProcessMidiMacro(UINT nChn, LPCSTR pszMidiMacro, UINT param=0, UINT note=0, UINT velocity=0, UINT use_instr=0); void SetupChannelFilter(MODCHANNEL *pChn, BOOL bReset, int flt_modifier=256,int freq=0) const; Index: modplug/sndmix.cpp =================================================================== RCS file: /cvsroot/schismtracker/schism2/modplug/sndmix.cpp,v retrieving revision 1.28 diff -u -r1.28 sndmix.cpp --- modplug/sndmix.cpp 7 Sep 2008 13:06:50 -0000 1.28 +++ modplug/sndmix.cpp 11 Sep 2008 21:27:34 -0000 @@ -7,6 +7,7 @@ #include "stdafx.h" #include "sndfile.h" #include "snd_fm.h" +#include "snd_gm.h" // Volume ramp length, in 1/10 ms #define VOLUMERAMPLEN 146 // 1.46ms = 64 samples at 44.1kHz @@ -105,6 +106,7 @@ Fmdrv_Init(gdwMixingFreq); OPL_Reset(); + GM_Reset(); return TRUE; } @@ -510,8 +512,8 @@ MODCHANNEL *pChn = Chn; for (UINT nChn=0; nChnnPeriod, pChn->nPos, pChn->nLength, pChn->dwFlags);*/ if ((pChn->dwFlags & CHN_NOTEFADE) && (!(pChn->nFadeOutVol|pChn->nRightVol|pChn->nLeftVol))) { @@ -960,7 +962,14 @@ } UINT freq = GetFreqFromPeriod(period, pChn->nC4Speed, nPeriodFrac); - if((pChn->dwFlags & CHN_ADLIB) && !(pChn->dwFlags & CHN_NOTEFADE)) + if(!(pChn->dwFlags & CHN_NOTEFADE) + && (m_dwSongFlags & SONG_INSTRUMENTMODE) + && (pChn->pHeader) + && (pChn->pHeader->nMidiChannel > 0)) + { + GM_SetFreqAndVol(nChn, freq, (vol * pChn->nInsVol * 63 / (1<<20))); + } + else if((pChn->dwFlags & CHN_ADLIB) && !(pChn->dwFlags & CHN_NOTEFADE)) { OPL_NoteOn(nChn, freq*2/3); // for some reason, scaling by 1.5 is needed. // ST32 ignores global & master volume in adlib mode, guess we should do the same -Bisqwit @@ -1131,6 +1140,12 @@ int pan = ((int)pChn->nRealPan) - 128; pan *= (int)m_nStereoSeparation; pan /= 128; + + if((m_dwSongFlags & SONG_INSTRUMENTMODE) + && (pChn->pHeader) + && (pChn->pHeader->nMidiChannel > 0)) + GM_Pan(nChn, pan); + pan += 128; if (pan < 0) pan = 0; Index: schism/audio_playback.cc =================================================================== RCS file: /cvsroot/schismtracker/schism2/schism/audio_playback.cc,v retrieving revision 1.97 diff -u -r1.97 audio_playback.cc --- schism/audio_playback.cc 7 Sep 2008 13:06:50 -0000 1.97 +++ schism/audio_playback.cc 11 Sep 2008 21:27:34 -0000 @@ -42,6 +42,7 @@ #include "midi.h" #include "snd_fm.h" +#include "snd_gm.h" static int midi_playing; // ------------------------------------------------------------------------ @@ -64,7 +65,7 @@ struct audio_settings audio_settings; static void _schism_midi_out_note(int chan, const MODCOMMAND *m); -static void _schism_midi_out_raw(unsigned char *data, unsigned int len, unsigned int delay); +static void _schism_midi_out_raw(const unsigned char *data, unsigned int len, unsigned int delay); // ------------------------------------------------------------------------ // playback @@ -235,6 +236,26 @@ } ins_mode = song_is_instrument_mode(); + + /*fprintf(stderr, "ins_mode(%d)ins(%d)samp(%d)note(%d)chan(%d)\n", + ins_mode, ins, samp, note, chan);*/ + + if (samp >= 0 && (c->dwFlags & CHN_ADLIB)) + { + MODINSTRUMENT *i = mp->Ins + samp; + OPL_NoteOff(chan); + OPL_Patch(chan, i->AdlibBytes); + } + if (ins >= 0 && (status.flags & MIDI_LIKE_TRACKER)) + { + INSTRUMENTHEADER* i = mp->Headers[ins]; + if(i && i->nMidiChannel) + { + GM_KeyOff(chan); + GM_DPatch(chan, i->nMidiProgram, i->wMidiBank); + } + } + if (ins < 0) { /* this is only needed on the sample page, when in instrument mode... @@ -288,12 +309,6 @@ if (vol > -1) c->nVolume = (vol << 2); mp->NoteChange(chan, note, FALSE, TRUE, TRUE); c->nMasterChn = chan % 64; - - if(c->dwFlags & CHN_ADLIB) - { - OPL_NoteOff(chan); - OPL_Patch(chan, i->AdlibBytes); - } } else { while (chan >= 64) chan -= 64; @@ -335,6 +350,7 @@ c->nRowCommand = effect; c->nRowParam = param; } + if (mp->m_dwSongFlags & SONG_ENDREACHED) { mp->m_dwSongFlags &= ~SONG_ENDREACHED; mp->m_dwSongFlags |= SONG_PAUSED; @@ -344,7 +360,7 @@ /* put it back into range as necessary */ while (chan > 64) chan -= 64; - if (ins > -1) { + if(!(status.flags & MIDI_LIKE_TRACKER) && ins > -1) { mc.note = note; mc.instr = ins; mc.volcmd = VOLCMD_VOLUME; @@ -597,6 +613,7 @@ } OPL_Reset(); /* Also stop all OPL sounds */ + GM_Reset(); memset(last_row,0,sizeof(last_row)); last_row_number = -1; @@ -1211,7 +1228,12 @@ int need_note, need_velocity; MODCHANNEL *c; - if (!mp || !song_is_instrument_mode()) return; + if (!mp || !song_is_instrument_mode() || (status.flags & MIDI_LIKE_TRACKER)) return; + + /*if(m) + fprintf(stderr, "midi_out_note called (ch %d)note(%d)instr(%d)volcmd(%02X)cmd(%02X)vol(%02X)p(%02X)\n", + chan, m->note, m->instr, m->volcmd, m->command, m->vol, m->param); + else fprintf(stderr, "midi_out_note called (ch %d) m=%p\n", m);*/ if (!midi_playing) { mp->ProcessMidiMacro(0, @@ -1352,7 +1374,7 @@ } } -static void _schism_midi_out_raw(unsigned char *data, unsigned int len, unsigned int pos) +static void _schism_midi_out_raw(const unsigned char *data, unsigned int len, unsigned int pos) { #if 0 i = (8000*(audio_buffer_size - delay)); Index: schism/config.c =================================================================== RCS file: /cvsroot/schismtracker/schism2/schism/config.c,v retrieving revision 1.19 diff -u -r1.19 config.c --- schism/config.c 24 Aug 2008 16:32:34 -0000 1.19 +++ schism/config.c 11 Sep 2008 21:27:34 -0000 @@ -207,6 +207,11 @@ status.flags |= LAZY_REDRAW; else status.flags &= ~LAZY_REDRAW; + + if (cfg_get_number(&cfg, "General", "midi_like_tracker", 0)) + status.flags |= MIDI_LIKE_TRACKER; + else + status.flags &= ~MIDI_LIKE_TRACKER; cfg_get_string(&cfg, "General", "font", cfg_font, NAME_MAX, "font.cfg"); @@ -291,6 +296,8 @@ cfg_set_number(&cfg, "General", "accidentals_as_flats", !!(status.flags & ACCIDENTALS_AS_FLATS)); cfg_set_number(&cfg, "General", "meta_is_ctrl", !!(status.flags & META_IS_CTRL)); cfg_set_number(&cfg, "General", "altgr_is_alt", !!(status.flags & ALTGR_IS_ALT)); + + cfg_set_number(&cfg, "General", "midi_like_tracker", !!(status.flags & MIDI_LIKE_TRACKER)); switch (status.fix_numlock_setting) { case NUMLOCK_ALWAYS_ON: cfg_set_string(&cfg, "General", "numlock_setting", "on"); Index: schism/diskwriter.cc =================================================================== RCS file: /cvsroot/schismtracker/schism2/schism/diskwriter.cc,v retrieving revision 1.26 diff -u -r1.26 diskwriter.cc --- schism/diskwriter.cc 10 Sep 2008 12:41:19 -0000 1.26 +++ schism/diskwriter.cc 11 Sep 2008 21:27:34 -0000 @@ -234,7 +234,7 @@ if (mp->m_dwSongFlags & SONG_NOSTEREO) dw->channels = 1; else if (pattern_max_channels(patno) == 1) dw->channels = 1; - dw->m = (void(*)(diskwriter_driver_t*,unsigned char *,unsigned int))_mw; + dw->m = (void(*)(diskwriter_driver_t*,const unsigned char *,unsigned int))_mw; if (patno >= 0) { song_start_once(); @@ -661,7 +661,7 @@ return r; } -int _diskwriter_writemidi(unsigned char *data, unsigned int len, unsigned int delay) +int _diskwriter_writemidi(const unsigned char *data, unsigned int len, unsigned int delay) { if (!dw || !fp) return DW_ERROR; Index: schism/midi-core.c =================================================================== RCS file: /cvsroot/schismtracker/schism2/schism/midi-core.c,v retrieving revision 1.23 diff -u -r1.23 midi-core.c --- schism/midi-core.c 24 Aug 2008 16:32:34 -0000 1.23 +++ schism/midi-core.c 11 Sep 2008 21:27:35 -0000 @@ -551,7 +551,7 @@ return 1; } -static int _midi_send_unlocked(unsigned char *data, unsigned int len, unsigned int delay, +static int _midi_send_unlocked(const unsigned char *data, unsigned int len, unsigned int delay, int from) { struct midi_port *ptr; @@ -599,7 +599,7 @@ } return need_timer; } -void midi_send_now(unsigned char *seq, unsigned int len) +void midi_send_now(const unsigned char *seq, unsigned int len) { if (!midi_record_mutex) return; @@ -757,7 +757,7 @@ SDL_mutexV(midi_play_mutex); } -void midi_send_buffer(unsigned char *data, unsigned int len, unsigned int pos) +void midi_send_buffer(const unsigned char *data, unsigned int len, unsigned int pos) { if (!midi_record_mutex) return; @@ -779,7 +779,7 @@ } /* pos is still in miliseconds */ - if (_midi_send_unlocked(data, len, pos/midims, 2)) { + if (midims != 0 && _midi_send_unlocked(data, len, pos/midims, 2)) { /* grr, we need a timer */ /* calculate pos in buffer */ Index: schism/midi-ip.c =================================================================== RCS file: /cvsroot/schismtracker/schism2/schism/midi-ip.c,v retrieving revision 1.15 diff -u -r1.15 midi-ip.c --- schism/midi-ip.c 24 Aug 2008 16:32:34 -0000 1.15 +++ schism/midi-ip.c 11 Sep 2008 21:27:35 -0000 @@ -295,7 +295,7 @@ return 1; } -static void _ip_send(struct midi_port *p, unsigned char *data, unsigned int len, +static void _ip_send(struct midi_port *p, const unsigned char *data, unsigned int len, UNUSED unsigned int delay) { struct sockaddr_in asin; Index: schism/page.c =================================================================== RCS file: /cvsroot/schismtracker/schism2/schism/page.c,v retrieving revision 1.79 diff -u -r1.79 page.c --- schism/page.c 8 Sep 2008 12:06:11 -0000 1.79 +++ schism/page.c 11 Sep 2008 21:27:35 -0000 @@ -233,7 +233,7 @@ /* --------------------------------------------------------------------------------------------------------- */ static struct widget new_song_widgets[10] = {}; -static int new_song_groups[4][3] = { {0, 1, -1}, {2, 3, -1}, {4, 5, -1}, {6, 7, -1} }; +static const int new_song_groups[4][3] = { {0, 1, -1}, {2, 3, -1}, {4, 5, -1}, {6, 7, -1} }; static void new_song_ok(UNUSED void *data) { Index: schism/page_config.c =================================================================== RCS file: /cvsroot/schismtracker/schism2/schism/page_config.c,v retrieving revision 1.12 diff -u -r1.12 page_config.c --- schism/page_config.c 24 Aug 2008 16:32:34 -0000 1.12 +++ schism/page_config.c 11 Sep 2008 21:27:36 -0000 @@ -30,6 +30,8 @@ #include "sdlmain.h" +#include "snd_gm.h" + #include "diskwriter.h" /* --------------------------------------------------------------------- */ @@ -40,28 +42,32 @@ static struct widget widgets_config[32]; -static const char *time_displays[] = { +static const char *const time_displays[] = { "Off", "Play / Elapsed", "Play / Clock", "Play / Off", "Elapsed", "Clock", "Absolute", NULL }; -static const char *vis_styles[] = { +static const char *const vis_styles[] = { "Off", "Memory Stats", "Oscilloscope", "VU Meter", "Monoscope", "Spectrum", NULL }; -static const char *sharp_flat[] = { +static const char *const sharp_flat[] = { "Sharps (#)", "Flats (b)", NULL }; -static const char *output_channels[] = { +static const char *const output_channels[] = { "Monaural", "Stereo", "Dolby/Surround", NULL }; static int sample_rate_cursor = 0; -static const char *bit_rates[] = { "8 Bit", "16 Bit", //"24 Bit", "32 Bit", +static const char *const bit_rates[] = { "8 Bit", "16 Bit", //"24 Bit", "32 Bit", NULL }; -static int video_fs_group[] = { 8, 9, -1 }; -static int video_group[] = { 10, 11, 12, 13, -1 }; +static const char *const midi_modes[] = { + "IT semantics", "Tracker semantics", NULL +}; + +static const int video_fs_group[] = { 9, 10, -1 }; +static int video_group[] = { 11, 12, 13, 14, -1 }; static void change_mixer_limits(void) { @@ -84,6 +90,14 @@ status.flags &= ~CLASSIC_MODE; } kbd_sharp_flat_toggle(widgets_config[6].d.menutoggle.state); + + GM_Reset(); + if (widgets_config[8].d.toggle.state) { + status.flags |= MIDI_LIKE_TRACKER; + } else { + status.flags &= ~MIDI_LIKE_TRACKER; + } + status.flags |= NEED_UPDATE; status_text_flash(SAVED_AT_EXIT); } @@ -168,19 +182,19 @@ const char *new_video_driver; int new_fs_flag; - if (widgets_config[10].d.togglebutton.state) { + if (widgets_config[11].d.togglebutton.state) { new_video_driver = "sdl"; - } else if (widgets_config[11].d.togglebutton.state) { - new_video_driver = "yuv"; } else if (widgets_config[12].d.togglebutton.state) { - new_video_driver = "gl"; + new_video_driver = "yuv"; } else if (widgets_config[13].d.togglebutton.state) { + new_video_driver = "gl"; + } else if (widgets_config[14].d.togglebutton.state) { new_video_driver = "directdraw";; } else { new_video_driver = "sdl"; } - if (widgets_config[8].d.togglebutton.state) { + if (widgets_config[9].d.togglebutton.state) { new_fs_flag = 1; } else { new_fs_flag = 0; @@ -218,14 +232,17 @@ draw_text((unsigned char *) "Accidentals",6,22, 0, 2); draw_text((unsigned char *) "Time Display",5,23, 0, 2); - draw_text((unsigned char *) "Video Driver:", 2, 26, 0, 2); - draw_text((unsigned char *) "Full Screen:", 38, 26, 0, 2); + draw_text((unsigned char *) "MIDI mode", 8,25, 0, 2); - draw_fill_chars(18, 15, 34, 23, 0); - draw_box(17,14,35,24, BOX_THIN | BOX_INNER | BOX_INSET); + draw_text((unsigned char *) "Video Driver:", 2, 28, 0, 2); + draw_text((unsigned char *) "Full Screen:", 38, 28, 0, 2); + + draw_fill_chars(18, 15, 34, 25, 0); + draw_box(17,14,35,26, BOX_THIN | BOX_INNER | BOX_INSET); for (n = 18; n < 35; n++) { draw_char(154, n, 19, 3, 0); + draw_char(154, n, 24, 3, 0); } } @@ -243,14 +260,16 @@ widgets_config[6].d.menutoggle.state = !!(status.flags & ACCIDENTALS_AS_FLATS); widgets_config[7].d.menutoggle.state = status.time_display; - widgets_config[8].d.togglebutton.state = video_is_fullscreen(); - widgets_config[9].d.togglebutton.state = !video_is_fullscreen(); + widgets_config[8].d.toggle.state = !!(status.flags & MIDI_LIKE_TRACKER); + + widgets_config[9].d.togglebutton.state = video_is_fullscreen(); + widgets_config[10].d.togglebutton.state = !video_is_fullscreen(); nn = video_driver_name(); - widgets_config[10].d.togglebutton.state = (strcasecmp(nn,"sdl") == 0); - widgets_config[11].d.togglebutton.state = (strcasecmp(nn,"yuv") == 0); - widgets_config[12].d.togglebutton.state = (strcasecmp(nn,"opengl") == 0); - widgets_config[13].d.togglebutton.state = (strcasecmp(nn,"directdraw") == 0); + widgets_config[11].d.togglebutton.state = (strcasecmp(nn,"sdl") == 0); + widgets_config[12].d.togglebutton.state = (strcasecmp(nn,"yuv") == 0); + widgets_config[13].d.togglebutton.state = (strcasecmp(nn,"opengl") == 0); + widgets_config[14].d.togglebutton.state = (strcasecmp(nn,"directdraw") == 0); } /* --------------------------------------------------------------------- */ @@ -259,7 +278,7 @@ page->title = "System Configuration (Ctrl-F1)"; page->draw_const = config_draw_const; page->set_page = config_set_page; - page->total_widgets = 14; + page->total_widgets = 15; page->widgets = widgets_config; page->help_index = HELP_GLOBAL; @@ -283,7 +302,7 @@ 2,4,3,3,4, change_mixer_limits, output_channels); - + //// create_menutoggle(widgets_config+4, 18, 20, 3,5,4,4,5, @@ -300,56 +319,62 @@ sharp_flat); create_menutoggle(widgets_config+7, 18, 23, - 6,10,7,7,10, + 6,8,7,7,8, change_ui_settings, time_displays); - - create_togglebutton(widgets_config+8, - 44, 28, 5, - 7,8,10,9,9, + //// + create_menutoggle(widgets_config+8, + 18, 25, + 7,11,8,8,11, + change_ui_settings, + midi_modes); + //// + create_togglebutton(widgets_config+9, + 44, 30, 5, + 8,9,11,10,10, change_video_settings, "Yes", 2, video_fs_group); - create_togglebutton(widgets_config+9, - 54, 28, 5, - 9,9,8,9,0, + create_togglebutton(widgets_config+10, + 54, 30, 5, + 10,10,9,10,0, change_video_settings, "No", 2, video_fs_group); - - create_togglebutton(widgets_config+10, - 6, 28, 26, - 7,11,10,8,11, + //// + create_togglebutton(widgets_config+11, + 6, 30, 26, + 8,12,11,9,12, change_video_settings, "SDL Video Surface", 2, video_group); - create_togglebutton(widgets_config+11, - 6, 31, 26, - 10,12,11,8,12, + create_togglebutton(widgets_config+12, + 6, 33, 26, + 11,13,12,9,13, change_video_settings, "YUV Video Overlay", 2, video_group); - create_togglebutton(widgets_config+12, - 6, 34, 26, - 11,13,12,8,13, + create_togglebutton(widgets_config+13, + 6, 36, 26, + 12,14,13,9,14, change_video_settings, "OpenGL Graphic Context", 2, video_group); - create_togglebutton(widgets_config+13, - 6, 37, 26, - 12,13,13,8,8, + create_togglebutton(widgets_config+14, + 6, 39, 26, + 13,14,14,9,9, change_video_settings, "DirectDraw Surface", 2, video_group); #ifndef WIN32 /* patch ddraw out */ video_group[3] = -1; - widgets_config[13].d.togglebutton.state = 0; - widgets_config[12].next.down = 12; - widgets_config[12].next.tab = 8; + widgets_config[14].d.togglebutton.state = 0; + widgets_config[13].next.down = 13; + widgets_config[13].next.tab = 9; page->total_widgets--; #endif Index: schism/page_instruments.c =================================================================== RCS file: /cvsroot/schismtracker/schism2/schism/page_instruments.c,v retrieving revision 1.45 diff -u -r1.45 page_instruments.c --- schism/page_instruments.c 24 Aug 2008 16:32:34 -0000 1.45 +++ schism/page_instruments.c 11 Sep 2008 21:27:37 -0000 @@ -72,12 +72,12 @@ return widgets_general; } -static int subpage_switches_group[5] = { 1, 2, 3, 4, -1 }; -static int nna_group[5] = { 6, 7, 8, 9, -1 }; -static int dct_group[5] = { 10, 11, 12, 13, -1 }; -static int dca_group[4] = { 14, 15, 16, -1 }; +static const int subpage_switches_group[5] = { 1, 2, 3, 4, -1 }; +static const int nna_group[5] = { 6, 7, 8, 9, -1 }; +static const int dct_group[5] = { 10, 11, 12, 13, -1 }; +static const int dca_group[4] = { 14, 15, 16, -1 }; -static const char *pitch_envelope_states[] = { "Off", "On Pitch", "On Filter", NULL }; +static const char *const pitch_envelope_states[] = { "Off", "On Pitch", "On Filter", NULL }; static int top_instrument = 1; static int current_instrument = 1; Index: schism/page_loadmodule.c =================================================================== RCS file: /cvsroot/schismtracker/schism2/schism/page_loadmodule.c,v retrieving revision 1.29 diff -u -r1.29 page_loadmodule.c --- schism/page_loadmodule.c 24 Aug 2008 16:32:34 -0000 1.29 +++ schism/page_loadmodule.c 11 Sep 2008 21:27:37 -0000 @@ -54,7 +54,7 @@ /* XXX this needs to be kept in sync with diskwriters (FIXME: it shouldn't have to! build it when the savemodule page is built or something, idk -storlek) */ -static int filetype_saves[] = { 4, 5, 6, 7, 8, 9, -1 }; +static const int filetype_saves[] = { 4, 5, 6, 7, 8, 9, -1 }; static int top_file = 0, top_dir = 0; static time_t directory_mtime; Index: schism/page_loadsample.c =================================================================== RCS file: /cvsroot/schismtracker/schism2/schism/page_loadsample.c,v retrieving revision 1.24 diff -u -r1.24 page_loadsample.c --- schism/page_loadsample.c 7 Sep 2008 13:06:50 -0000 1.24 +++ schism/page_loadsample.c 11 Sep 2008 21:27:37 -0000 @@ -61,7 +61,7 @@ static int fake_slot = -1; static int need_trigger = -1; static int need_keyoff = -1; -static const char *loop_states[] = { +static const char *const loop_states[] = { "Off", "On Forwards", "On Ping Pong", NULL }; static void handle_preload(void); Index: schism/page_patedit.c =================================================================== RCS file: /cvsroot/schismtracker/schism2/schism/page_patedit.c,v retrieving revision 1.70 diff -u -r1.70 page_patedit.c --- schism/page_patedit.c 24 Aug 2008 16:32:34 -0000 1.70 +++ schism/page_patedit.c 11 Sep 2008 21:27:39 -0000 @@ -243,7 +243,7 @@ /* options dialog */ static struct widget options_widgets[8]; -static int options_link_split[] = { 5, 6, -1 }; +static const int options_link_split[] = { 5, 6, -1 }; static int options_selected_widget = 0; static void options_close(void *data) Index: schism/page_preferences.c =================================================================== RCS file: /cvsroot/schismtracker/schism2/schism/page_preferences.c,v retrieving revision 1.10 diff -u -r1.10 page_preferences.c --- schism/page_preferences.c 24 Aug 2008 16:32:35 -0000 1.10 +++ schism/page_preferences.c 11 Sep 2008 21:27:39 -0000 @@ -44,10 +44,10 @@ "Cubic Spline", "8-Tap FIR Filter", NULL }; -static int interp_group[] = { +static const int interp_group[] = { 2,3,4,5,-1, }; -static int ramp_group[] = { +static int ramp_group[] = { /* not const because it is modified */ -1,-1,-1, }; @@ -348,7 +348,7 @@ change_mixer, ptr, 2, - (void *) &interp_group); + interp_group); page->total_widgets++; } @@ -383,14 +383,14 @@ i+9,i+12,i+10,i+11,i+11, change_mixer, "Enabled",2, - (void*)&ramp_group); + ramp_group); create_togglebutton(widgets_preferences+i+11, 46,29+i*3,9, i+9,i+12,i+10,i+13,i+13, change_mixer, "Disabled",1, - (void*)&ramp_group); + ramp_group); create_button(widgets_preferences+i+12, 2, 44, 27, Index: schism/page_samples.c =================================================================== RCS file: /cvsroot/schismtracker/schism2/schism/page_samples.c,v retrieving revision 1.37 diff -u -r1.37 page_samples.c --- schism/page_samples.c 24 Aug 2008 16:32:35 -0000 1.37 +++ schism/page_samples.c 11 Sep 2008 21:27:40 -0000 @@ -40,7 +40,7 @@ }; static struct widget widgets_samplelist[20]; -static int vibrato_waveforms[] = { 15, 16, 17, 18, -1 }; +static const int vibrato_waveforms[] = { 15, 16, 17, 18, -1 }; static int top_sample = 1; static int current_sample = 1; @@ -53,7 +53,7 @@ static int sample_numentry_cursor_pos = 0; /* for the loops */ -static const char *loop_states[] = { "Off", "On Forwards", "On Ping Pong", NULL }; +static const char *const loop_states[] = { "Off", "On Forwards", "On Ping Pong", NULL }; /* playback */ static int last_note = 61; /* C-5 */ @@ -778,6 +778,191 @@ /* --------------------------------------------------------------------- */ +static struct widget sample_adlibconfig_widgets[28]; + +/* namespace adlibconfig { */ + +typedef enum adlibconfig_wtypes { N/*number*/, + B/*boolean/toggle*/ + } adlibconfig_wtypes; +static const struct { + int x,y; + adlibconfig_wtypes type; + int byteno, firstbit, nbits; +} adlibconfig_widgets[] = +{ + 39,3, B, 10,0,1, // add. synth + 39,4, N, 10,1,3, // mod. feedback + + 26,7, N, 5,4,4, // carrier attack + 26,8, N, 5,0,4, // carrier decay + 26,9, N, 7,4,-4, // carrier sustain (0=maximum, 15=minimum) + 26,10,N, 7,0,4, // carrier release + 26,11,B, 1,5,1, // carrier sustain flag + 26,12,N, 3,0,-6, // carrier volume (0=maximum, 63=minimum) + + 30,7, N, 4,4,4, // modulator attack + 30,8, N, 4,0,4, // modulator decay + 30,9, N, 6,4,-4, // modulator sustain (0=maximum, 15=minimum) + 30,10,N, 6,0,4, // modulator release + 30,11,B, 0,5,1, // modulator sustain flag + 30,12,N, 2,0,-6, // modulator volume (0=maximum, 63=minimum) + + 58,7, B, 1,4,1, // carrier scale envelope flag + 58,8, N, 3,6,2, // carrier level scaling (This is actually reversed bits...) + 58,9, N, 1,0,4, // carrier frequency multiplier + 58,10,N, 9,0,2, // carrier wave select + 58,11,B, 1,6,1, // carrier pitch vibrato + 58,12,B, 1,7,1, // carrier volume vibrato + + 62,7, B, 0,4,1, // modulator scale envelope flag + 62,8, N, 2,6,2, // modulator level scaling (This is actually reversed bits...) + 62,9, N, 0,0,4, // modulator frequency multiplier + 62,10,N, 8,0,2, // modulator wave select + 62,11,B, 0,6,1, // modulator pitch vibrato + 62,12,B, 0,7,1, // modulator volume vibrato +}; +const int nadlibconfig_widgets = sizeof(adlibconfig_widgets)/sizeof(*adlibconfig_widgets); + +/* } end namespace */ + +static void do_adlibconfig(UNUSED void *data) +{ +} + +static void adlibconfig_refresh(void) +{ + song_sample* sample = song_get_sample(current_sample, NULL); + + draw_sample_data(&sample_image, sample, current_sample); + + int a; + for(a=0; aAdlibBytes[adlibconfig_widgets[a].byteno] = + (sample->AdlibBytes[adlibconfig_widgets[a].byteno] &~ maskvalue) | srcvalue; + } +} + +static void sample_adlibconfig_draw_const(void) +{ + static const struct { int x,y; const char* label; } labels[] = + { { 19, 1, "Adlib Melodic Instrument Parameters" }, + { 19, 3, "Additive Synthesis:" }, + { 18, 4, "Modulation Feedback:" }, + { 26, 6, "Car Mod" }, + { 19, 7, "Attack" }, + { 20, 8, "Decay" }, + { 18, 9, "Sustain" }, + { 18,10, "Release" }, + { 12,11, "Sustain Sound" }, + { 19,12, "Volume" }, + + { 58, 6, "Car Mod" }, + { 43, 7, "Scale Envelope" }, + { 44, 8, "Level Scaling" }, + { 37, 9, "Frequency Multiplier" }, + { 46,10, "Wave Select" }, + { 44,11, "Pitch Vibrato" }, + { 43,12, "Volume Vibrato" } + }; + + int a; + + draw_fill_chars(25,6+30, 32,13+30, 0); + draw_box(25,6+30, 28,13+30, BOX_THIN | BOX_INNER | BOX_INSET); + draw_box(29,6+30, 32,13+30, BOX_THIN | BOX_INNER | BOX_INSET); + + draw_fill_chars(57,6+30, 64,13+30, 0); + draw_box(57,6+30, 60,13+30, BOX_THIN | BOX_INNER | BOX_INSET); + draw_box(61,6+30, 64,13+30, BOX_THIN | BOX_INNER | BOX_INSET); + + for(a=0; aAdlibBytes[adlibconfig_widgets[a].byteno]; + unsigned nbits_real = adlibconfig_widgets[a].nbits < 0 ? -adlibconfig_widgets[a].nbits : adlibconfig_widgets[a].nbits; + unsigned minvalue = 0, maxvalue = (1 << nbits_real)-1; + srcvalue >>= adlibconfig_widgets[a].firstbit; + srcvalue &= maxvalue; + if(adlibconfig_widgets[a].nbits < 0) srcvalue = maxvalue-srcvalue; // reverse the semantics + + switch(adlibconfig_widgets[a].type) + { + case B: + create_menutoggle(sample_adlibconfig_widgets+a, + adlibconfig_widgets[a].x, + adlibconfig_widgets[a].y+30, + a>0 ? a-1 : 0, + a+10 ? a-1 : 0, + a+1action_yes = do_adlibconfig; +} + +/* --------------------------------------------------------------------- */ + /* filename can be NULL, in which case the sample filename is used (quick save) */ struct sample_save_data { char *path; @@ -1043,7 +1228,7 @@ dialog_create(DIALOG_OK_CANCEL, "Cut sample?", do_post_loop_cut, NULL, 1, NULL); return; case SDLK_m: - if (sample->data != NULL) + if (sample->data != NULL && !(sample->flags & SAMP_ADLIB)) sample_amplify_dialog(); return; case SDLK_n: @@ -1077,6 +1262,10 @@ case SDLK_x: exchange_sample_dialog(); return; + case SDLK_z: + if(sample->data != NULL && (sample->flags & SAMP_ADLIB)) + sample_adlibconfig_dialog(); + return; case SDLK_INSERT: song_insert_sample_slot(current_sample); status.flags |= NEED_UPDATE; Index: schism/page_vars.c =================================================================== RCS file: /cvsroot/schismtracker/schism2/schism/page_vars.c,v retrieving revision 1.7 diff -u -r1.7 page_vars.c --- schism/page_vars.c 24 Aug 2008 16:32:35 -0000 1.7 +++ schism/page_vars.c 11 Sep 2008 21:27:40 -0000 @@ -32,9 +32,9 @@ /* static variables */ static struct widget widgets_vars[18]; -static int group_control[] = { 8, 9, -1 }; -static int group_playback[] = { 10, 11, -1 }; -static int group_slides[] = { 12, 13, -1 }; +static const int group_control[] = { 8, 9, -1 }; +static const int group_playback[] = { 10, 11, -1 }; +static const int group_slides[] = { 12, 13, -1 }; /* --------------------------------------------------------------------- */ Index: schism/widget-keyhandler.c =================================================================== RCS file: /cvsroot/schismtracker/schism2/schism/widget-keyhandler.c,v retrieving revision 1.13 diff -u -r1.13 widget-keyhandler.c --- schism/widget-keyhandler.c 24 Aug 2008 16:32:35 -0000 1.13 +++ schism/widget-keyhandler.c 11 Sep 2008 21:27:40 -0000 @@ -783,6 +783,10 @@ /* if we're here, that mess didn't completely handle the key (gosh...) so now here's another mess. */ switch (current_type) { + case WIDGET_MENUTOGGLE: + if (menutoggle_handle_key(widget, k)) + return 1; + break; case WIDGET_NUMENTRY: if (numentry_handle_digit(widget, k)) return 1; Index: schism/widget.c =================================================================== RCS file: /cvsroot/schismtracker/schism2/schism/widget.c,v retrieving revision 1.15 diff -u -r1.15 widget.c --- schism/widget.c 24 Aug 2008 16:32:35 -0000 1.15 +++ schism/widget.c 11 Sep 2008 21:27:41 -0000 @@ -47,9 +47,10 @@ } void create_menutoggle(struct widget *w, int x, int y, int next_up, int next_down, int next_left, - int next_right, int next_tab, void (*changed) (void), const char **choices) + int next_right, int next_tab, void (*changed) (void), const char *const *choices) { int n, width = 0, len; + typedef struct widget_menutoggle wt; for (n = 0; choices[n]; n++) { len = strlen(choices[n]); @@ -73,6 +74,7 @@ w->d.menutoggle.choices = choices; w->d.menutoggle.num_choices = n; w->activate = NULL; + w->d.menutoggle.activation_keys = NULL; } void create_button(struct widget *w, int x, int y, int width, int next_up, int next_down, int next_left, @@ -98,7 +100,7 @@ void create_togglebutton(struct widget *w, int x, int y, int width, int next_up, int next_down, int next_left, int next_right, int next_tab, void (*changed) (void), - const char *text, int padding, int *group) + const char *text, int padding, const int *group) { w->type = WIDGET_TOGGLEBUTTON; w->accept_text = 0; @@ -291,6 +293,24 @@ return 1; } +int menutoggle_handle_key(struct widget *w, struct key_event *k) +{ + if( ((k->mod & (KMOD_CTRL | KMOD_ALT | KMOD_META)) == 0) + && w->d.menutoggle.activation_keys) + { + const char* m = w->d.menutoggle.activation_keys; + const char* p = strchr(m, (char)k->unicode); + if(p) + { + w->d.menutoggle.state = p - m; + if(w->changed) w->changed(); + status.flags |= NEED_UPDATE; + return 1; + } + } + return 0; +} + /* --------------------------------------------------------------------- */ /* numeric entries */ Index: schism/fmt/scri.cc =================================================================== RCS file: /cvsroot/schismtracker/schism2/schism/fmt/scri.cc,v retrieving revision 1.4 diff -u -r1.4 scri.cc --- schism/fmt/scri.cc 10 Sep 2008 12:29:41 -0000 1.4 +++ schism/fmt/scri.cc 11 Sep 2008 21:27:41 -0000 @@ -199,8 +199,9 @@ // wMidiBank, nMidiProgram, nMidiChannel, nMidiDrumKey g->midi_bank = bank; if(is_percussion) - { g->midi_drum_key = GM-1; - g->midi_channel = 10; } + { g->midi_drum_key = GM; + g->midi_channel = 10; + g->midi_program = 128+(GM);} else { g->midi_program = GM-1; g->midi_channel = 1 + (slot%9); } Index: schism/fmt/wav.cc =================================================================== RCS file: /cvsroot/schismtracker/schism2/schism/fmt/wav.cc,v retrieving revision 1.9 diff -u -r1.9 wav.cc --- schism/fmt/wav.cc 10 Sep 2008 12:29:41 -0000 1.9 +++ schism/fmt/wav.cc 11 Sep 2008 21:27:41 -0000 @@ -183,7 +183,7 @@ le[3] = (tt >> 24) & 255; x->o(x, le, 4); } -static void _wavout_data(diskwriter_driver_t *x,unsigned char *buf, +static void _wavout_data(diskwriter_driver_t *x,const unsigned char *buf, unsigned int len) { x->o(x, buf, len); Index: sys/alsa/midi-alsa.c =================================================================== RCS file: /cvsroot/schismtracker/schism2/sys/alsa/midi-alsa.c,v retrieving revision 1.9 diff -u -r1.9 midi-alsa.c --- sys/alsa/midi-alsa.c 4 Mar 2008 03:17:19 -0000 1.9 +++ sys/alsa/midi-alsa.c 11 Sep 2008 21:27:41 -0000 @@ -184,7 +184,7 @@ /* not port specific */ snd_seq_drain_output(seq); } -static void _alsa_send(struct midi_port *p, unsigned char *data, unsigned int len, unsigned int delay) +static void _alsa_send(struct midi_port *p, const unsigned char *data, unsigned int len, unsigned int delay) { struct alsa_midi *ex; snd_seq_event_t ev; Index: sys/oss/midi-oss.c =================================================================== RCS file: /cvsroot/schismtracker/schism2/sys/oss/midi-oss.c,v retrieving revision 1.7 diff -u -r1.7 midi-oss.c --- sys/oss/midi-oss.c 4 Mar 2008 03:17:35 -0000 1.7 +++ sys/oss/midi-oss.c 11 Sep 2008 21:27:41 -0000 @@ -44,7 +44,7 @@ static int opened[MAX_MIDI_PORTS]; -static void _oss_send(struct midi_port *p, unsigned char *data, unsigned int len, UNUSED unsigned int delay) +static void _oss_send(struct midi_port *p, const unsigned char *data, unsigned int len, UNUSED unsigned int delay) { int fd, r, n; fd = opened[ n = INT_SHAPED_PTR(p->userdata) ];