…Show last 1745 lines
61+
62+void MIDI_ClearBuffer(Bit8u slot) {
63+ midi.sysex.used=0;
64+ midi.status=0x00;
65+ midi.cmd_pos=0;
66+ midi.cmd_len=0;
67+}
68+
69 void MIDI_RawOutByte(Bit8u data) {
70 if (midi.sysex.start) {
71 Bit32u passed_ticks = GetTicks() - midi.sysex.start;
72@@ -168,6 +195,9 @@ public:
73 Section_prop * section=static_cast<Section_prop *>(configuration);
74 const char * dev=section->Get_string("mididevice");
75 std::string fullconf=section->Get_string("midiconfig");
76+
77+ const char * inconf = 1; // change to integer value of midi input device
78+
79 /* If device = "default" go for first handler that works */
80 MidiHandler * handler;
81 // MAPPER_AddHandler(MIDI_SaveRawEvent,MK_f8,MMOD1|MMOD2,"caprawmidi","Cap MIDI");
82@@ -183,6 +213,7 @@ public:
83 midi.status=0x00;
84 midi.cmd_pos=0;
85 midi.cmd_len=0;
86+ midi.sysex.used=0;
87 if (!strcasecmp(dev,"default")) goto getdefault;
88 handler=handler_list;
89 while (handler) {
90@@ -194,7 +225,7 @@ public:
91 midi.handler=handler;
92 midi.available=true;
93 LOG(LOG_MISC,LOG_DEBUG)("MIDI: Opened device:%s",handler->GetName());
94- return;
95+ goto midiin;
96 }
97 handler=handler->next;
98 }
99@@ -206,16 +237,27 @@ getdefault:
100 midi.available=true;
101 midi.handler=handler;
102 LOG(LOG_MISC,LOG_DEBUG)("MIDI: Opened device:%s",handler->GetName());
103- return;
104+ goto midiin;
105 }
106 handler=handler->next;
107 }
108 /* This shouldn't be possible */
109 }
110+midiin:
111+ MidiHandler * output_handler=0;
112+ output_handler=handler;
113+ if (handler->OpenInput(inconf)) {
114+ LOG_MSG("MIDI:Opened input device:%s.",handler->GetName());
115+ midi.in_handler=handler;
116+ return;
117+ }
118+ handler=handler_list;
119 ~MIDI(){
120+ midi.in_handler->Close();
121 if(midi.available) midi.handler->Close();
122 midi.available = false;
123 midi.handler = 0;
124+ midi.in_handler = 0;
125 }
126 };
127
128diff -rupN dosbox-before//src/gui/midi_win32.h dosbox-after/src/gui/midi_win32.h
129--- dosbox-before//src/gui/midi_win32.h
130+++ dosbox-after/src/gui/midi_win32.h
131@@ -25,14 +25,60 @@
132 #include <string>
133 #include <sstream>
134
135+void CALLBACK Win32_midiInCallback(HMIDIIN hMidiIn, UINT wMsg, DWORD_PTR dwInstance, DWORD_PTR dwParam1, DWORD_PTR dwParam2) {
136+ //LOG_MSG("wMsg:%x %x %x",wMsg, dwParam1, dwParam2);
137+ Bit8u msg[4] = {(Bit8u(dwParam1&0xff)),(Bit8u((dwParam1&0xff00)>>8)),
138+ (Bit8u((dwParam1&0xff0000)>>16)),MIDI_evt_len[(Bit8u(dwParam1&0xff))]};
139+ Bit8u *sysex;
140+ Bitu len;
141+ MIDIHDR *t_hdr;
142+ switch (wMsg) {
143+ case MM_MIM_DATA: /* 0x3C3 - midi message */
144+ MIDI_InputMsg(msg);
145+ break;
146+ case MM_MIM_OPEN: /* 0x3C1 */
147+ break;
148+ case MM_MIM_CLOSE: /* 0x3C2 */
149+ break;
150+ case MM_MIM_LONGDATA: /* 0x3C4 - sysex */
151+ t_hdr=(MIDIHDR*)dwParam1;
152+ sysex=(Bit8u*)t_hdr->lpData;
153+ len=(Bitu)t_hdr->dwBytesRecorded;
154+ {
155+ Bitu cnt=5;
156+ while (cnt) { //abort if timed out
157+ Bitu ret = Bitu(MIDI_InputSysex(sysex,len,false));
158+ if (!ret) {len=0;break;}
159+ if (len==ret) cnt--; else cnt=5;
160+ sysex+=len-ret;
161+ len=ret;
162+ Sleep(5);//msec
163+ }
164+ if (len) MIDI_InputSysex(sysex,0,false);
165+ }
166+ midiInUnprepareHeader(hMidiIn,t_hdr,sizeof(*t_hdr));
167+ t_hdr->dwBytesRecorded = 0 ;
168+ midiInPrepareHeader(hMidiIn,t_hdr,sizeof(*t_hdr));
169+ break;
170+ case MM_MIM_ERROR:
171+ case MM_MIM_LONGERROR:
172+ break;
173+ default:
174+ LOG(LOG_MISC, LOG_NORMAL) ("MIDI: Unhandled input type %x",wMsg);
175+ }
176+};
177+
178 class MidiHandler_win32: public MidiHandler {
179 private:
180 HMIDIOUT m_out;
181 MIDIHDR m_hdr;
182 HANDLE m_event;
183 bool isOpen;
184+ HMIDIIN m_in;
185+ MIDIHDR m_inhdr;
186+ bool isOpenInput;
187 public:
188- MidiHandler_win32() : MidiHandler(),isOpen(false) {};
189+ MidiHandler_win32() : isOpen(false),isOpenInput(false),MidiHandler() {};
190 const char * GetName(void) { return "win32";};
191 bool Open(const char * conf) {
192 if (isOpen) return false;
193@@ -71,12 +117,46 @@ public:
194 isOpen=true;
195 return true;
196 };
197+ bool OpenInput(const char *inconf) {
198+ if (isOpenInput) return false;
199+ void * midiInCallback=Win32_midiInCallback;
200+ MMRESULT res;
201+ if(inconf && *inconf) {
202+ std::string strinconf(inconf);
203+ std::istringstream configmidiin(strinconf);
204+ unsigned int nummer = midiInGetNumDevs();
205+ configmidiin >> nummer;
206+ if(nummer < midiInGetNumDevs()){
207+ MIDIINCAPS mididev;
208+ midiInGetDevCaps(nummer, &mididev, sizeof(MIDIINCAPS));
209+ LOG_MSG("MIDI:win32 selected input %s",mididev.szPname);
210+ res = midiInOpen (&m_in, nummer, (DWORD_PTR)midiInCallback, 0, CALLBACK_FUNCTION);
211+ }
212+ } else {
213+ res = midiInOpen(&m_in, MIDI_MAPPER, (DWORD_PTR)midiInCallback, 0, CALLBACK_FUNCTION);
214+ }
215+ if (res != MMSYSERR_NOERROR) return false;
216
217+ m_inhdr.lpData = (char*)&MIDI_InSysexBuf[0];
218+ m_inhdr.dwBufferLength = SYSEX_SIZE;
219+ m_inhdr.dwBytesRecorded = 0 ;
220+ m_inhdr.dwUser = 0;
221+ midiInPrepareHeader(m_in,&m_inhdr,sizeof(m_inhdr));
222+ midiInStart(m_in);
223+ isOpenInput=true;
224+ return true;
225+ };
226 void Close(void) {
227- if (!isOpen) return;
228- isOpen=false;
229- midiOutClose(m_out);
230- CloseHandle (m_event);
231+ if (isOpen) {
232+ isOpen=false;
233+ midiOutClose(m_out);
234+ CloseHandle (m_event);
235+ }
236+ if (isOpenInput) {
237+ isOpenInput=false;
238+ midiInStop(m_in);
239+ midiInClose(m_in);
240+ }
241 };
242 void PlayMsg(Bit8u * msg) {
243 midiOutShortMsg(m_out, *(Bit32u*)msg);
244diff -rupN dosbox-before//src/hardware/mpu401.cpp dosbox-after/src/hardware/mpu401.cpp
245--- dosbox-before//src/hardware/mpu401.cpp
246+++ dosbox-after/src/hardware/mpu401.cpp
247@@ -24,22 +24,38 @@
248 #include "setup.h"
249 #include "cpu.h"
250 #include "support.h"
251+#include "mixer.h"
252+#include "midi.h"
253
254 void MIDI_RawOutByte(Bit8u data);
255 bool MIDI_Available(void);
256+SDL_mutex * MPULock;
257
258 static void MPU401_Event(Bitu);
259 static void MPU401_Reset(void);
260 static void MPU401_ResetDone(Bitu);
261 static void MPU401_EOIHandler(Bitu val=0);
262 static void MPU401_EOIHandlerDispatch(void);
263+static void MPU401_IntelligentOut(Bitu data);
264+static void MPU401_WriteCommand(Bitu port,Bitu val,Bitu iolen);
265+static void MPU401_WriteData(Bitu port,Bitu val,Bitu iolen);
266+static void MPU401_NotesOff(Bitu chan);
267+static void MPU401_RecQueueBuffer(Bit8u * buf, Bitu len,bool block);
268
269 #define MPU401_VERSION 0x15
270 #define MPU401_REVISION 0x01
271-#define MPU401_QUEUE 32
272+#define MPU401_QUEUE 64
273+#define MPU401_INPUT_QUEUE 1024
274 #define MPU401_TIMECONSTANT (60000000/1000.0f)
275 #define MPU401_RESETBUSY 27.0f
276
277+#define M_GETKEY key[key/32]&(1<<(key%32))
278+#define M_SETKEY key[key/32]|=(1<<(key%32))
279+#define M_DELKEY key[key/32]&=~(1<<(key%32))
280+enum RecState { M_RECOFF,M_RECSTB,M_RECON };
281+static Bitu MPUClockBase[8]={48,72,96,120,144,168,192};
282+static Bit8u cth_data[16]={0,0,0,0,1,0,0,0,1,0,1,0,1,1,1,0};
283+
284 enum MpuMode { M_UART,M_INTELLIGENT };
285 enum MpuDataType {T_OVERFLOW,T_MARK,T_MIDI_SYS,T_MIDI_NORM,T_COMMAND};
286
287@@ -58,20 +74,38 @@ static void MPU401_WriteData(Bitu port,B
288 #define MSG_MPU_ACK 0xfe
289
290 static struct {
291+ bool intelligent;
292+ Bitu irq;
293+ bool midi_thru;
294+ IO_ReadHandleObject ReadHandler[2];
295+ IO_WriteHandleObject WriteHandler[2];
296+} mpuhw;
297+
298+static struct {
299 bool intelligent;
300 MpuMode mode;
301 Bitu irq;
302 Bit8u queue[MPU401_QUEUE];
303 Bitu queue_pos,queue_used;
304+ Bit8u rec_queue[MPU401_INPUT_QUEUE];
305+ Bitu rec_queue_pos,rec_queue_used;
306 struct track {
307 Bits counter;
308- Bit8u value[8],sys_val;
309- Bit8u vlength,length;
310+ Bit8u value[3],sys_val;
311+ Bitu length;
312 MpuDataType type;
313 } playbuf[8],condbuf;
314 struct {
315- bool conductor,cond_req,cond_set, block_ack;
316- bool playing,reset;
317+ bool tx_ready;
318+ bool conductor,cond_req,cond_set;
319+ bool track_req;
320+ bool block_ack;
321+ bool playing;
322+ bool clock_to_host;
323+ bool sync_in;
324+ bool sysex_in_finished;
325+ bool rec_copy;
326+ RecState rec;
327 bool wsd,wsm,wsd_start;
328 bool run_irq,irq_pending;
329 bool send_now;
330@@ -81,220 +115,470 @@ static struct {
331 Bit8u tmask,cmask,amask;
332 Bit16u midi_mask;
333 Bit16u req_mask;
334- Bit8u channel,old_chan;
335+ Bitu track,old_track;
336+ Bit8u last_rtcmd;
337 } state;
338 struct {
339 Bit8u timebase,old_timebase;
340 Bit8u tempo,old_tempo;
341 Bit8u tempo_rel,old_tempo_rel;
342 Bit8u tempo_grad;
343- Bit8u cth_rate,cth_counter;
344- bool clock_to_host,cth_active;
345+ Bit8u cth_rate[4],cth_mode;
346+ Bit8u midimetro,metromeas;
347+ Bitu cth_counter,cth_old;
348+ Bitu rec_counter;
349+ Bit32s measure_counter,meas_old;
350+ Bit32s freq;
351+ Bits ticks_in;
352+ float freq_mod;
353+ bool active;
354 } clock;
355+ struct {
356+ bool all_thru,midi_thru,sysex_thru,commonmsgs_thru;
357+ bool modemsgs_in, commonmsgs_in, bender_in, sysex_in;
358+ bool allnotesoff_out;
359+ bool rt_affection, rt_out,rt_in;
360+ bool timing_in_stop;
361+ bool data_in_stop;
362+ bool rec_measure_end;
363+ Bit8u prchg_buf[16];
364+ Bit16u prchg_mask;
365+ } filter;
366+ Bitu ch_toref[16];
367+ struct {
368+ Bit8u chan;
369+ Bit32u key[4];
370+ Bit8u trmask;
371+ bool on;
372+ }chanref[5],inputref[16];
373 } mpu;
374
375+static void MPU401_ReCalcClock(void) {
376+ Bit32s maxtempo=240, mintempo=16;
377+ if (mpu.clock.timebase>=168) maxtempo=179;
378+ if (mpu.clock.timebase==144) maxtempo=208;
379+ if (mpu.clock.timebase>=120) mintempo=8;
380+ mpu.clock.freq=(Bit32u(mpu.clock.tempo*2*mpu.clock.tempo_rel))>>6;
381+
382+ mpu.clock.freq=mpu.clock.timebase*
383+ (mpu.clock.freq<(mintempo*2) ? mintempo :
384+ ((mpu.clock.freq/2)<maxtempo?(mpu.clock.freq/2):maxtempo) );
385+
386+ if (mpu.state.sync_in) {
387+ Bit32s freq= Bit32s(float(mpu.clock.freq)*mpu.clock.freq_mod);
388+ if (freq>mpu.clock.timebase*mintempo && freq<mpu.clock.timebase*maxtempo)
389+ mpu.clock.freq=freq;
390+ }
391+}
392+
393+static INLINE void MPU401_StartClock(void) {
394+ if (mpu.clock.active) return;
395+ if (!(mpu.state.clock_to_host || mpu.state.playing || mpu.state.rec==M_RECON)) return;
396+ mpu.clock.active=true;
397+ PIC_RemoveEvents(MPU401_Event);
398+ PIC_AddEvent(MPU401_Event,MPU401_TIMECONSTANT/mpu.clock.freq);
399+}
400+
401+static void MPU401_StopClock(void) {
402+ if (mpu.state.playing || mpu.state.rec!=M_RECON || mpu.state.clock_to_host) return;
403+ mpu.clock.active=false;
404+ PIC_RemoveEvents(MPU401_Event);
405+}
406+
407 int MPU401_GetIRQ() {
408 return (int)mpu.irq;
409 }
410
411-static void QueueByte(Bit8u data) {
412+static INLINE void MPU401_RunClock(void) {
413+ if (!mpu.clock.active) return;
414+ PIC_RemoveEvents(MPU401_Event);
415+ PIC_AddEvent(MPU401_Event,MPU401_TIMECONSTANT/(mpu.clock.freq));
416+}
417+
418+static INLINE void MPU401_QueueByte(Bit8u data) {
419 if (mpu.state.block_ack) {mpu.state.block_ack=false;return;}
420- if (mpu.queue_used==0 && mpu.intelligent) {
421+ if (mpu.queue_used==0 && mpuhw.intelligent) {
422 mpu.state.irq_pending=true;
423- PIC_ActivateIRQ(mpu.irq);
424+ PIC_ActivateIRQ(mpuhw.irq);
425 }
426 if (mpu.queue_used<MPU401_QUEUE) {
427 Bitu pos=mpu.queue_used+mpu.queue_pos;
428- if (mpu.queue_pos>=MPU401_QUEUE) mpu.queue_pos-=MPU401_QUEUE;
429 if (pos>=MPU401_QUEUE) pos-=MPU401_QUEUE;
430 mpu.queue_used++;
431 mpu.queue[pos]=data;
432- } else LOG(LOG_MISC,LOG_NORMAL)("MPU401:Data queue full");
433+ }
434+}
435+
436+static void MPU401_RecQueueBuffer(Bit8u * buf, Bitu len,bool block) {
437+ if (block) {
438+ if (MPULock) SDL_mutexP(MPULock);
439+ else return;
440+ }
441+ Bitu cnt=0;
442+ while (cnt<len) {
443+ if (mpu.rec_queue_used<MPU401_INPUT_QUEUE) {
444+ Bitu pos=mpu.rec_queue_used+mpu.rec_queue_pos;
445+ if (pos>=MPU401_INPUT_QUEUE) {pos-=MPU401_INPUT_QUEUE;}
446+ mpu.rec_queue[pos]=buf[cnt];
447+ mpu.rec_queue_used++;
448+ if (!mpu.state.sysex_in_finished && buf[cnt]==MSG_EOX) {//finish sysex
449+ mpu.state.sysex_in_finished=true;
450+ break;
451+ }
452+ cnt++;
453+ }
454+ }
455+ if (mpu.queue_used==0) {
456+ if (mpu.state.rec_copy || mpu.state.irq_pending) {
457+ if (block && MPULock) SDL_mutexV(MPULock);
458+ return;
459+ }
460+ mpu.state.rec_copy=true;
461+ if (mpu.rec_queue_pos>=MPU401_INPUT_QUEUE) mpu.rec_queue_pos-=MPU401_INPUT_QUEUE;
462+ MPU401_QueueByte(mpu.rec_queue[mpu.rec_queue_pos]);
463+ mpu.rec_queue_used--;
464+ mpu.rec_queue_pos++;
465+ }
466+ if (block && MPULock) SDL_mutexV(MPULock);
467 }
468
469-static void ClrQueue(void) {
470+static void MPU401_ClrQueue(void) {
471 mpu.queue_used=0;
472 mpu.queue_pos=0;
473+ mpu.rec_queue_used=0;
474+ mpu.rec_queue_pos=0;
475+ mpu.state.sysex_in_finished=true;
476+ mpu.state.irq_pending=false;
477 }
478
479 static Bitu MPU401_ReadStatus(Bitu port,Bitu iolen) {
480 (void)iolen;//UNUSED
481 (void)port;//UNUSED
482- Bit8u ret=0x3f; /* Bits 6 and 7 clear */
483- if (mpu.state.cmd_pending) ret|=0x40;
484- if (!mpu.queue_used) ret|=0x80;
485- return ret;
486+ return (0x3f | (mpu.queue_used ? 0: 0x80));
487+}
488+
489+static Bitu MPU401_ReadStatusTx(Bitu port,Bitu iolen) {
490+ return (0x3f | (mpu.queue_used ? 0: 0x80) | (mpu.state.tx_ready ? 0: 0x40));
491+}
492+
493+
494+void MPU401_SetTx(bool status) {
495+ mpu.state.tx_ready=status;
496 }
497
498 static void MPU401_WriteCommand(Bitu port,Bitu val,Bitu iolen) {
499- (void)iolen;//UNUSED
500- (void)port;//UNUSED
501- if (mpu.mode==M_UART && val!=0xff) return;
502- if (mpu.state.reset) {
503- if (mpu.state.cmd_pending || (val!=0x3f && val!=0xff)) {
504- mpu.state.cmd_pending=val+1;
505- return;
506- }
507- PIC_RemoveEvents(MPU401_ResetDone);
508- mpu.state.reset=false;
509- }
510- if (val<=0x2f) {
511- switch (val&3) { /* MIDI stop, start, continue */
512- case 1: {MIDI_RawOutByte(0xfc);break;}
513- case 2: {MIDI_RawOutByte(0xfa);break;}
514- case 3: {MIDI_RawOutByte(0xfb);break;}
515- }
516- if (val&0x20) LOG(LOG_MISC,LOG_ERROR)("MPU-401:Unhandled Recording Command %x",(int)val);
517- switch (val&0xc) {
518- case 0x4: /* Stop */
519- PIC_RemoveEvents(MPU401_Event);
520- mpu.state.playing=false;
521- for (Bitu i=0xb0;i<0xbf;i++) { /* All notes off */
522- MIDI_RawOutByte(i);
523- MIDI_RawOutByte(0x7b);
524- MIDI_RawOutByte(0);
525- }
526- break;
527- case 0x8: /* Play */
528- LOG(LOG_MISC,LOG_NORMAL)("MPU-401:Intelligent mode playback started");
529- mpu.state.playing=true;
530- PIC_RemoveEvents(MPU401_Event);
531- PIC_AddEvent(MPU401_Event,MPU401_TIMECONSTANT/(mpu.clock.tempo*mpu.clock.timebase));
532- ClrQueue();
533- break;
534- }
535- }
536- else if (val>=0xa0 && val<=0xa7) { /* Request play counter */
537- if (mpu.state.cmask&(1<<(val&7))) QueueByte(mpu.playbuf[val&7].counter);
538- }
539- else if (val>=0xd0 && val<=0xd7) { /* Send data */
540- mpu.state.old_chan=mpu.state.channel;
541- mpu.state.channel=val&7;
542- mpu.state.wsd=true;
543- mpu.state.wsm=false;
544- mpu.state.wsd_start=true;
545- }
546- else
547- switch (val) {
548- case 0xdf: /* Send system message */
549- mpu.state.wsd=false;
550- mpu.state.wsm=true;
551- mpu.state.wsd_start=true;
552+ //LOG(LOG_MISC,LOG_NORMAL)("MPU401:command %x",val);
553+ SDL_mutexP(MPULock);
554+
555+ //hack:enable midi through after the first mpu401 command is written
556+ mpuhw.midi_thru=true;
557+
558+ if (val<=0x2f) { /* Sequencer state */
559+ bool send_prchg=false;
560+ if ((val&0xf)<0xc) {
561+ switch (val&3) { /* MIDI realtime messages */
562+ case 1:
563+ mpu.state.last_rtcmd=0xfc;
564+ if (mpu.filter.rt_out) MIDI_RawOutRTByte(0xfc);
565+ mpu.clock.meas_old=mpu.clock.measure_counter;
566+ mpu.clock.cth_old=mpu.clock.cth_counter;
567+ break;
568+ case 2:
569+ mpu.state.last_rtcmd=0xfa;
570+ if (mpu.filter.rt_out) MIDI_RawOutRTByte(0xfb);
571+ mpu.clock.measure_counter=mpu.clock.meas_old=0;
572+ mpu.clock.cth_counter=mpu.clock.cth_old=0;
573+ break;
574+ case 3:
575+ mpu.state.last_rtcmd=0xfc;
576+ if (mpu.filter.rt_out) MIDI_RawOutRTByte(0xfa);
577+ mpu.clock.measure_counter=mpu.clock.meas_old;
578+ mpu.clock.cth_counter=mpu.clock.cth_old;
579+ break;
580+ }
581+ switch (val&0xc) { /* Playing */
582+ case 0x4: /* Stop */
583+ mpu.state.playing=false;
584+ MPU401_StopClock();
585+ for (Bitu i=0;i<16;i++) MPU401_NotesOff(i);
586+ mpu.filter.prchg_mask=0;
587+ break;
588+ case 0x8: /* Start */
589+ LOG(LOG_MISC,LOG_NORMAL)("MPU-401:Intelligent mode playback");
590+ mpu.state.playing=true;
591+ MPU401_StartClock();
592+ }
593+ switch (val&0x30) { /* Recording */
594+ case 0: //check if it waited for MIDI RT command
595+ //if (val&8 && mpu.state.rec!=M_RECON) mpu.clock.rec_counter=0;
596+ if ((val&3)<2 || !mpu.filter.rt_affection || mpu.state.rec!=M_RECSTB) break;
597+ mpu.state.rec=M_RECON;
598+ MPU401_StartClock();
599+ if (mpu.filter.prchg_mask) send_prchg=true;
600+ break;
601+ case 0x10: /* Stop */
602+ //if (val&8 && mpu.state.rec!=M_RECON) mpu.clock.rec_counter=0;
603+ mpu.state.rec=M_RECOFF;
604+ MPU401_StopClock();
605+ MPU401_QueueByte(MSG_MPU_ACK);
606+ MPU401_QueueByte(mpu.clock.rec_counter);
607+ MPU401_QueueByte(MSG_MPU_END);
608+ mpu.filter.prchg_mask=0;
609+ mpu.clock.rec_counter=0;
610+ SDL_mutexV(MPULock);
611+ return;
612+ case 0x20: /* Start */
613+ LOG(LOG_MISC,LOG_NORMAL)("MPU-401: intelligent mode recording");
614+ if (!(mpu.state.rec==M_RECON)) {
615+ mpu.clock.rec_counter=0;
616+ mpu.state.rec=M_RECSTB;
617+ }
618+ if (mpu.state.last_rtcmd==0xfa || mpu.state.last_rtcmd==0xfb) {
619+ mpu.clock.rec_counter=0;
620+ mpu.state.rec=M_RECON;
621+ if (mpu.filter.prchg_mask) send_prchg=true;
622+ MPU401_StartClock();
623+ }
624+ }
625+ }
626+ MPU401_QueueByte(MSG_MPU_ACK);
627+ //record counter hack: needed by Prism, but sent only on cmd 0x20/0x26 (or breaks Ballade)
628+ Bit8u rec_cnt=mpu.clock.rec_counter;
629+ if ((val==0x20 || val==0x26) && mpu.state.rec==M_RECON)
630+ MPU401_RecQueueBuffer(&rec_cnt,1,false);
631+
632+ if (send_prchg) for (Bitu i=0;i<16;i++)
633+ if (mpu.filter.prchg_mask&(1<<i)) {
634+ Bit8u recmsg[3]={mpu.clock.rec_counter,0xc0|i,mpu.filter.prchg_buf[i]};
635+ MPU401_RecQueueBuffer(recmsg,3,false);
636+ mpu.filter.prchg_mask&=~(1<<i);
637+ }
638+ SDL_mutexV(MPULock);
639+ return;
640+ }
641+ else if (val>=0xa0 && val<=0xa7) { /* Request play counter */
642+ //if (mpu.state.cmask&(1<<(val&7)))
643+ MPU401_QueueByte(mpu.playbuf[val&7].counter);
644+ }
645+ else if (val>=0xd0 && val<=0xd7) { /* Send data */
646+ mpu.state.old_track=mpu.state.track;
647+ mpu.state.track=val&7;
648+ mpu.state.wsd=true;
649+ mpu.state.wsm=false;
650+ mpu.state.wsd_start=true;
651+ }
652+ else if (val<0x80 && val>=0x40) { /* Set reference table channel */
653+ mpu.chanref[(val>>4)-4].on=true;
654+ mpu.chanref[(val>>4)-4].chan=val&0x0f;
655+ mpu.chanref[(val>>4)-4].trmask=0;
656+ for (Bitu i=0;i<4;i++) mpu.chanref[(val>>4)-4].key[i]=0;
657+ for (Bitu i=0;i<16;i++) if (mpu.ch_toref[i]==((val>>4)-4)) mpu.ch_toref[i]=4;
658+ mpu.ch_toref[val&0x0f]=(val>>4)-4;
659+ }
660+ else
661+ switch (val) {
662+ case 0x30: /* Configuration 0x30 - 0x39 */
663+ mpu.filter.allnotesoff_out=false;
664+ break;
665+ case 0x32:
666+ mpu.filter.rt_out=false;
667+ break;
668+ case 0x33:
669+ mpu.filter.all_thru=false;
670+ mpu.filter.commonmsgs_thru=false;
671+ mpu.filter.midi_thru=false;
672+ for (Bitu i=0;i<16;i++) {
673+ mpu.inputref[i].on=false;
674+ for (Bitu j=0;j<4;j++) mpu.inputref[i].key[j]=0;
675+ }
676+ break;
677+ case 0x34:
678+ mpu.filter.timing_in_stop=true;
679+ break;
680+ case 0x35:
681+ mpu.filter.modemsgs_in=true;
682+ break;
683+ case 0x37:
684+ mpu.filter.sysex_thru=true;
685 break;
686- case 0x8e: /* Conductor */
687- mpu.state.cond_set=false;
688+ case 0x38:
689+ mpu.filter.commonmsgs_in=true;
690 break;
691- case 0x8f:
692- mpu.state.cond_set=true;
693+ case 0x39:
694+ mpu.filter.rt_in=true;
695 break;
696+ case 0x3f: /* UART mode */
697+ LOG(LOG_MISC,LOG_NORMAL)("MPU-401:Set UART mode %X",val);
698+ mpu.mode=M_UART;
699+ mpuhw.midi_thru=false;
700+ break;
701+ case 0x80: /* Internal clock */
702+ if (mpu.clock.active && mpu.state.sync_in) {
703+ PIC_AddEvent(MPU401_Event,MPU401_TIMECONSTANT/(mpu.clock.freq));
704+ mpu.clock.freq_mod=1.0;
705+ }
706+ mpu.state.sync_in=false;
707+ break;
708+ case 0x82: /* Sync to MIDI */
709+ mpu.clock.ticks_in=0;
710+ mpu.state.sync_in=true;
711+ break;
712+ case 0x86: case 0x87: /* Bender */
713+ mpu.filter.bender_in=bool(val&1);
714+ break;
715+ case 0x88: case 0x89:/* MIDI through */
716+ mpu.filter.midi_thru=bool(val&1);
717+ for (Bitu i=0;i<16;i++) {
718+ mpu.inputref[i].on=mpu.filter.midi_thru;
719+ if (!(val&1)) for (Bitu j=0;j<4;j++) mpu.inputref[i].key[j]=0;
720+ }
721+ break;
722+ case 0x8a: case 0x8b: /* Data in stop */
723+ mpu.filter.data_in_stop=bool(val&1);
724+ break;
725+ case 0x8c: case 0x8d: /* Send measure end */
726+ mpu.filter.rec_measure_end=bool(val&1);
727+ break;
728+ case 0x8e: case 0x8f: /* Conductor */
729+ mpu.state.cond_set=bool(val&1);
730+ break;
731+ case 0x90: case 0x91: /* Realtime affection */
732+ mpu.filter.rt_affection=bool(val&1);
733+ break;
734 case 0x94: /* Clock to host */
735- mpu.clock.clock_to_host=false;
736- break;
737+ mpu.state.clock_to_host=false;
738+ MPU401_StopClock();
739+ break;
740 case 0x95:
741- mpu.clock.clock_to_host=true;
742- break;
743- case 0xc2: /* Internal timebase */
744- mpu.clock.timebase=48;
745- break;
746- case 0xc3:
747- mpu.clock.timebase=72;
748- break;
749- case 0xc4:
750- mpu.clock.timebase=96;
751- break;
752- case 0xc5:
753- mpu.clock.timebase=120;
754- break;
755- case 0xc6:
756- mpu.clock.timebase=144;
757+ mpu.state.clock_to_host=true;
758+ MPU401_StartClock();
759 break;
760- case 0xc7:
761- mpu.clock.timebase=168;
762- break;
763- case 0xc8:
764- mpu.clock.timebase=192;
765- break;
766- /* Commands with data byte */
767- case 0xe0: case 0xe1: case 0xe2: case 0xe4: case 0xe6:
768- case 0xe7: case 0xec: case 0xed: case 0xee: case 0xef:
769- mpu.state.command_byte=val;
770- break;
771- /* Commands 0xa# returning data */
772- case 0xab: /* Request and clear recording counter */
773- QueueByte(MSG_MPU_ACK);
774- QueueByte(0);
775- return;
776- case 0xac: /* Request version */
777- QueueByte(MSG_MPU_ACK);
778- QueueByte(MPU401_VERSION);
779- return;
780- case 0xad: /* Request revision */
781- QueueByte(MSG_MPU_ACK);
782- QueueByte(MPU401_REVISION);
783- return;
784- case 0xaf: /* Request tempo */
785- QueueByte(MSG_MPU_ACK);
786- QueueByte(mpu.clock.tempo);
787- return;
788- case 0xb1: /* Reset relative tempo */
789- mpu.clock.old_tempo_rel=mpu.clock.tempo_rel;
790- mpu.clock.tempo_rel=0x40;
791+ case 0x96: case 0x97: /* Sysex input allow */
792+ mpu.filter.sysex_in=bool(val&1);
793+ if (val&1) mpu.filter.sysex_thru=false;
794+ break;
795+ case 0x98:case 0x99:case 0x9a: case 0x9b: /* Reference tables on/off */
796+ case 0x9c:case 0x9d:case 0x9e: case 0x9f:
797+ mpu.chanref[(val-0x98)/2].on=bool(val&1);
798+ break;
799+ /* Commands 0xa# returning data */
800+ case 0xab: /* Request and clear recording counter */
801+ MPU401_QueueByte(MSG_MPU_ACK);
802+ MPU401_QueueByte(0);
803+ SDL_mutexV(MPULock);
804+ return;
805+ case 0xac: /* Request version */
806+ MPU401_QueueByte(MSG_MPU_ACK);
807+ MPU401_QueueByte(MPU401_VERSION);
808+ SDL_mutexV(MPULock);
809+ return;
810+ case 0xad: /* Request revision */
811+ MPU401_QueueByte(MSG_MPU_ACK);
812+ MPU401_QueueByte(MPU401_REVISION);
813+ SDL_mutexV(MPULock);
814+ return;
815+ case 0xaf: /* Request tempo */
816+ MPU401_QueueByte(MSG_MPU_ACK);
817+ MPU401_QueueByte(mpu.clock.tempo);
818+ SDL_mutexV(MPULock);
819+ return;
820+ case 0xb1: /* Reset relative tempo */
821+ mpu.clock.tempo_rel=0x40;
822+ break;
823+ case 0xb8: /* Clear play counters */
824+ mpu.state.last_rtcmd=0;
825+ for (Bitu i=0;i<8;i++) {
826+ mpu.playbuf[i].counter=0;
827+ mpu.playbuf[i].type=T_OVERFLOW;
828+ }
829+ mpu.condbuf.counter=0;
830+ mpu.condbuf.type=T_OVERFLOW;
831+
832+ mpu.state.amask=mpu.state.tmask;
833+ mpu.state.conductor=mpu.state.cond_set;
834+ mpu.clock.cth_counter=mpu.clock.cth_old=0;
835+ mpu.clock.measure_counter=mpu.clock.meas_old=0;
836 break;
837 case 0xb9: /* Clear play map */
838- case 0xb8: /* Clear play counters */
839- for (Bitu i=0xb0;i<0xbf;i++) { /* All notes off */
840- MIDI_RawOutByte(i);
841- MIDI_RawOutByte(0x7b);
842- MIDI_RawOutByte(0);
843- }
844+ for (Bitu i=0;i<16;i++) MPU401_NotesOff(i);
845 for (Bitu i=0;i<8;i++) {
846 mpu.playbuf[i].counter=0;
847 mpu.playbuf[i].type=T_OVERFLOW;
848 }
849- mpu.condbuf.counter=0;
850- mpu.condbuf.type=T_OVERFLOW;
851- if (!(mpu.state.conductor=mpu.state.cond_set)) mpu.state.cond_req=0;
852- mpu.state.amask=mpu.state.tmask;
853- mpu.state.req_mask=0;
854- mpu.state.irq_pending=true;
855- break;
856- case 0xff: /* Reset MPU-401 */
857- LOG(LOG_MISC,LOG_NORMAL)("MPU-401:Reset %X",(int)val);
858- PIC_AddEvent(MPU401_ResetDone,MPU401_RESETBUSY);
859- mpu.state.reset=true;
860- if (mpu.mode==M_UART) {
861- MPU401_Reset();
862- return; //do not send ack in UART mode
863- }
864- MPU401_Reset();
865+ mpu.state.last_rtcmd=0;
866+ mpu.clock.cth_counter=mpu.clock.cth_old=0;
867+ mpu.clock.measure_counter=mpu.clock.meas_old=0;
868+ break;
869+ case 0xba: /* Clear record counter */
870+ mpu.clock.rec_counter=0;
871+ break;
872+ case 0xc2: case 0xc3: case 0xc4: /* Internal timebase */
873+ case 0xc5: case 0xc6: case 0xc7: case 0xc8:
874+ mpu.clock.timebase=MPUClockBase[val-0xc2];
875+ MPU401_ReCalcClock();
876 break;
877- case 0x3f: /* UART mode */
878- LOG(LOG_MISC,LOG_NORMAL)("MPU-401:Set UART mode %X",(int)val);
879- mpu.mode=M_UART;
880+ case 0xdf: /* Send system message */
881+ mpu.state.wsd=false;
882+ mpu.state.wsm=true;
883+ mpu.state.wsd_start=true;
884 break;
885- default:;
886- //LOG(LOG_MISC,LOG_NORMAL)("MPU-401:Unhandled command %X",val);
887- }
888- QueueByte(MSG_MPU_ACK);
889+ case 0xe0: case 0xe1: case 0xe2: case 0xe4: case 0xe6: /* Commands with data byte */
890+ case 0xe7: case 0xec: case 0xed: case 0xee: case 0xef:
891+ mpu.state.command_byte=val;
892+ break;
893+ case 0xff: /* Reset MPU-401 */
894+ LOG(LOG_MISC,LOG_NORMAL)("MPU-401:Reset");
895+ if (CPU_Cycles > 5) { //It came from the desert wants a fast irq
896+ CPU_CycleLeft += CPU_Cycles;
897+ CPU_Cycles = 5;
898+ }
899+ MPU401_Reset();
900+ break;
901+ default:;
902+ //LOG(LOG_MISC,LOG_WARN)("MPU-401:Unhandled command %X",val);
903+ }
904+ MPU401_QueueByte(MSG_MPU_ACK);
905+ SDL_mutexV(MPULock);
906 }
907
908 static Bitu MPU401_ReadData(Bitu port,Bitu iolen) {
909 (void)iolen;//UNUSED
910 (void)port;//UNUSED
911+ SDL_mutexP(MPULock);
912+
913 Bit8u ret=MSG_MPU_ACK;
914 if (mpu.queue_used) {
915 if (mpu.queue_pos>=MPU401_QUEUE) mpu.queue_pos-=MPU401_QUEUE;
916 ret=mpu.queue[mpu.queue_pos];
917 mpu.queue_pos++;mpu.queue_used--;
918 }
919- if (!mpu.intelligent) return ret;
920-
921- if (mpu.queue_used == 0) PIC_DeActivateIRQ(mpu.irq);
922+ if (mpu.mode==M_UART) {
923+ if (mpuhw.intelligent && !mpu.queue_used) PIC_DeActivateIRQ(mpuhw.irq);
924+ SDL_mutexV(MPULock);
925+ return ret;
926+ }
927+ if (mpu.state.rec_copy && !mpu.rec_queue_used) {
928+ mpu.state.rec_copy=false;
929+ MPU401_EOIHandler();
930+ SDL_mutexV(MPULock);
931+ //LOG(LOG_MISC,LOG_NORMAL)("MPU401:read data eoi %x", ret);
932+ return ret;
933+ }
934+
935+ //copy from recording buffer
936+ if (!mpu.queue_used && mpu.rec_queue_used) {
937+ mpu.state.rec_copy=true;
938+ if (mpu.rec_queue_pos>=MPU401_INPUT_QUEUE) mpu.rec_queue_pos-=MPU401_INPUT_QUEUE;
939+ MPU401_QueueByte(mpu.rec_queue[mpu.rec_queue_pos]);
940+ mpu.rec_queue_pos++;mpu.rec_queue_used--;
941+ }
942+ if (!mpu.queue_used) PIC_DeActivateIRQ(mpuhw.irq);
943
944 if (ret>=0xf0 && ret<=0xf7) { /* MIDI data request */
945- mpu.state.channel=ret&7;
946+ mpu.state.track=ret&7;
947 mpu.state.data_onoff=0;
948 mpu.state.cond_req=false;
949+ mpu.state.track_req=true;
950 }
951 if (ret==MSG_MPU_COMMAND_REQ) {
952 mpu.state.data_onoff=0;
953@@ -303,36 +587,50 @@ static Bitu MPU401_ReadData(Bitu port,Bi
954 mpu.state.block_ack=true;
955 MPU401_WriteCommand(0x331,mpu.condbuf.value[0],1);
956 if (mpu.state.command_byte) MPU401_WriteData(0x330,mpu.condbuf.value[1],1);
957+ mpu.condbuf.type=T_OVERFLOW;
958 }
959- mpu.condbuf.type=T_OVERFLOW;
960 }
961- if (ret==MSG_MPU_END || ret==MSG_MPU_CLOCK || ret==MSG_MPU_ACK) {
962- mpu.state.data_onoff=-1;
963+ if (ret==MSG_MPU_END || ret==MSG_MPU_CLOCK || ret==MSG_MPU_ACK || ret==MSG_MPU_OVERFLOW)
964 MPU401_EOIHandlerDispatch();
965 }
966+ SDL_mutexV(MPULock);
967+ //LOG(LOG_MISC,LOG_NORMAL)("MPU401:read data %x", ret);
968 return ret;
969 }
970
971 static void MPU401_WriteData(Bitu port,Bitu val,Bitu iolen) {
972 (void)iolen;//UNUSED
973 (void)port;//UNUSED
974- if (mpu.mode==M_UART) {MIDI_RawOutByte(val);return;}
975+ //LOG(LOG_MISC,LOG_NORMAL)("MPU401:write data %x", val);
976+ if (mpu.mode==M_UART) {MIDI_RawOutByte(val,MOUT_MPU);return;}
977+ static Bitu length,cnt;
978+
979 switch (mpu.state.command_byte) { /* 0xe# command data */
980 case 0x00:
981 break;
982 case 0xe0: /* Set tempo */
983 mpu.state.command_byte=0;
984- mpu.clock.tempo=val;
985+ if (mpu.clock.tempo<8) mpu.clock.tempo=8;
986+ else if (mpu.clock.tempo>250) mpu.clock.tempo=250;
987+ else mpu.clock.tempo=val;
988+ MPU401_ReCalcClock();
989 return;
990 case 0xe1: /* Set relative tempo */
991 mpu.state.command_byte=0;
992 mpu.clock.old_tempo_rel=mpu.clock.tempo_rel;
993 mpu.clock.tempo_rel=val;
994- if (val != 0x40) LOG(LOG_MISC,LOG_ERROR)("MPU-401:Relative tempo change value 0x%x (%.3f)",(unsigned int)val,(double)val / 0x40);
995+ mpu.clock.tempo_rel=val;
996+ MPU401_ReCalcClock();
997+ return;
998+ case 0xe2: /* Set gradation for relative tempo */
999+ mpu.clock.tempo_grad=val;
1000+ mpu.state.command_byte=0;
1001 return;
1002 case 0xe7: /* Set internal clock to host interval */
1003 mpu.state.command_byte=0;
1004- mpu.clock.cth_rate=val>>2;
1005+ if (!val) val=64;
1006+ for (Bitu i=0;i<4;i++) mpu.clock.cth_rate[i]=(val>>2)+cth_data[(val&3)*4+i];
1007+ mpu.clock.cth_mode=0;
1008 return;
1009 case 0xec: /* Set active track mask */
1010 mpu.state.command_byte=0;
1011@@ -352,46 +650,46 @@ static void MPU401_WriteData(Bitu port,B
1012 mpu.state.midi_mask&=0x00ff;
1013 mpu.state.midi_mask|=((Bit16u)val)<<8;
1014 return;
1015- //case 0xe2: /* Set graduation for relative tempo */
1016- //case 0xe4: /* Set metronome */
1017- //case 0xe6: /* Set metronome measure length */
1018 default:
1019 mpu.state.command_byte=0;
1020 return;
1021 }
1022- static Bitu length,cnt,posd;
1023- if (mpu.state.wsd) { /* Directly send MIDI message */
1024+ if (mpu.state.wsd && !mpu.state.track_req && !mpu.state.cond_req) { /* Directly send MIDI message */
1025 if (mpu.state.wsd_start) {
1026 mpu.state.wsd_start=0;
1027 cnt=0;
1028- switch (val&0xf0) {
1029- case 0xc0:case 0xd0:
1030- mpu.playbuf[mpu.state.channel].value[0]=val;
1031- length=2;
1032- break;
1033- case 0x80:case 0x90:case 0xa0:case 0xb0:case 0xe0:
1034- mpu.playbuf[mpu.state.channel].value[0]=val;
1035- length=3;
1036- break;
1037- case 0xf0:
1038- LOG(LOG_MISC,LOG_ERROR)("MPU-401:Illegal WSD byte");
1039- mpu.state.wsd=0;
1040- mpu.state.channel=mpu.state.old_chan;
1041- return;
1042- default: /* MIDI with running status */
1043- cnt++;
1044- MIDI_RawOutByte(mpu.playbuf[mpu.state.channel].value[0]);
1045- }
1046+ switch (val&0xf0) {
1047+ case 0xc0:case 0xd0:
1048+ length=mpu.playbuf[mpu.state.track].length=2;
1049+ mpu.playbuf[mpu.state.track].type=T_MIDI_NORM;
1050+ break;
1051+ case 0x80:case 0x90:case 0xa0:case 0xb0:case 0xe0:
1052+ length=mpu.playbuf[mpu.state.track].length=3;
1053+ mpu.playbuf[mpu.state.track].type=T_MIDI_NORM;
1054+ break;
1055+ case 0xf0:
1056+ LOG(LOG_MISC,LOG_WARN)("MPU-401:Illegal MIDI voice message: %x",val);
1057+ mpu.state.wsd=0;
1058+ mpu.state.track=mpu.state.old_track;
1059+ return;
1060+ default: /* MIDI with running status */
1061+ cnt++;
1062+ length=mpu.playbuf[mpu.state.track].length;
1063+ mpu.playbuf[mpu.state.track].type=T_MIDI_NORM;
1064+ }
1065+ }
1066+ if (cnt<length) {
1067+ mpu.playbuf[mpu.state.track].value[cnt]=val;
1068+ cnt++;
1069 }
1070- if (cnt<length) {MIDI_RawOutByte(val);cnt++;}
1071 if (cnt==length) {
1072+ MPU401_IntelligentOut(mpu.state.track);
1073 mpu.state.wsd=0;
1074- mpu.state.channel=mpu.state.old_chan;
1075+ mpu.state.track=mpu.state.old_track;
1076 }
1077 return;
1078 }
1079- if (mpu.state.wsm) { /* Directly send system message */
1080- if (val==MSG_EOX) {MIDI_RawOutByte(MSG_EOX);mpu.state.wsm=0;return;}
1081+ if (mpu.state.wsm && !mpu.state.track_req && !mpu.state.cond_req) { /* Send system message */
1082 if (mpu.state.wsd_start) {
1083 mpu.state.wsd_start=0;
1084 cnt=0;
1085@@ -401,24 +699,37 @@ static void MPU401_WriteData(Bitu port,B
1086 case 0xf6:{ length=1; break;}
1087 case 0xf0:{ length=0; break;}
1088 default:
1089- length=0;
1090+ LOG(LOG_MISC,LOG_WARN)
1091+ ("MPU401:Illegal MIDI system common/exclusive message: %x",val);
1092+ mpu.state.wsm=0;
1093+ return;
1094 }
1095+ } else if (val&0x80) {
1096+ MIDI_RawOutByte(MSG_EOX,MOUT_MPU);
1097+ mpu.state.wsm=0;
1098+ return;
1099+ }
1100+ if (!length || cnt<length) {
1101+ MIDI_RawOutByte(val,MOUT_MPU);
1102+ cnt++;
1103 }
1104- if (!length || cnt<length) {MIDI_RawOutByte(val);cnt++;}
1105 if (cnt==length) mpu.state.wsm=0;
1106 return;
1107 }
1108+ SDL_mutexP(MPULock);
1109 if (mpu.state.cond_req) { /* Command */
1110 switch (mpu.state.data_onoff) {
1111 case -1:
1112+ SDL_mutexV(MPULock);
1113 return;
1114 case 0: /* Timing byte */
1115- mpu.condbuf.vlength=0;
1116+ mpu.condbuf.length=0;
1117 if (val<0xf0) mpu.state.data_onoff++;
1118 else {
1119+ mpu.state.cond_req=false;
1120 mpu.state.data_onoff=-1;
1121 MPU401_EOIHandlerDispatch();
1122- return;
1123+ break;
1124 }
1125 if (val==0) mpu.state.send_now=true;
1126 else mpu.state.send_now=false;
1127@@ -426,148 +737,203 @@ static void MPU401_WriteData(Bitu port,B
1128 break;
1129 case 1: /* Command byte #1 */
1130 mpu.condbuf.type=T_COMMAND;
1131- if (val==0xf8 || val==0xf9) mpu.condbuf.type=T_OVERFLOW;
1132- mpu.condbuf.value[mpu.condbuf.vlength]=val;
1133- mpu.condbuf.vlength++;
1134- if ((val&0xf0)!=0xe0) MPU401_EOIHandlerDispatch();
1135+ if (val==0xf8 || val==0xf9 || val==0xfc) mpu.condbuf.type=T_OVERFLOW;
1136+ mpu.condbuf.value[mpu.condbuf.length]=val;
1137+ mpu.condbuf.length++;
1138+ if ((val&0xf0)!=0xe0) { //no cmd data byte
1139+ MPU401_EOIHandler();
1140+ mpu.state.data_onoff=-1;
1141+ mpu.state.cond_req=false;
1142+ }
1143 else mpu.state.data_onoff++;
1144 break;
1145 case 2:/* Command byte #2 */
1146- mpu.condbuf.value[mpu.condbuf.vlength]=val;
1147- mpu.condbuf.vlength++;
1148+ mpu.condbuf.value[mpu.condbuf.length]=val;
1149+ mpu.condbuf.length++;
1150 MPU401_EOIHandlerDispatch();
1151+ mpu.state.data_onoff=-1;
1152+ mpu.state.cond_req=false;
1153 break;
1154 }
1155+ SDL_mutexV(MPULock);
1156 return;
1157 }
1158 switch (mpu.state.data_onoff) { /* Data */
1159 case -1:
1160- return;
1161+ break;
1162 case 0: /* Timing byte */
1163- if (val<0xf0) mpu.state.data_onoff=1;
1164+ if (val<0xf0) mpu.state.data_onoff++;
1165 else {
1166 mpu.state.data_onoff=-1;
1167 MPU401_EOIHandlerDispatch();
1168+ mpu.state.track_req=false;
1169+ SDL_mutexV(MPULock);
1170 return;
1171 }
1172 if (val==0) mpu.state.send_now=true;
1173 else mpu.state.send_now=false;
1174- mpu.playbuf[mpu.state.channel].counter=(Bits)val;
1175+ mpu.playbuf[mpu.state.track].counter=val;
1176 break;
1177- case 1: /* MIDI */
1178- mpu.playbuf[mpu.state.channel].vlength++;
1179- posd=mpu.playbuf[mpu.state.channel].vlength;
1180- if (posd==1) {
1181- switch (val&0xf0) {
1182- case 0xf0: /* System message or mark */
1183- if (val>0xf7) {
1184- mpu.playbuf[mpu.state.channel].type=T_MARK;
1185- mpu.playbuf[mpu.state.channel].sys_val=val;
1186- length=1;
1187- } else {
1188- LOG(LOG_MISC,LOG_ERROR)("MPU-401:Illegal message");
1189- mpu.playbuf[mpu.state.channel].type=T_MIDI_SYS;
1190- mpu.playbuf[mpu.state.channel].sys_val=val;
1191- length=1;
1192- }
1193- break;
1194- case 0xc0: case 0xd0: /* MIDI Message */
1195- mpu.playbuf[mpu.state.channel].type=T_MIDI_NORM;
1196- length=mpu.playbuf[mpu.state.channel].length=2;
1197- break;
1198- case 0x80: case 0x90: case 0xa0: case 0xb0: case 0xe0:
1199- mpu.playbuf[mpu.state.channel].type=T_MIDI_NORM;
1200- length=mpu.playbuf[mpu.state.channel].length=3;
1201- break;
1202- default: /* MIDI data with running status */
1203- posd++;
1204- mpu.playbuf[mpu.state.channel].vlength++;
1205- mpu.playbuf[mpu.state.channel].type=T_MIDI_NORM;
1206- length=mpu.playbuf[mpu.state.channel].length;
1207- break;
1208+ case 1: /* MIDI */
1209+ cnt=0;
1210+ mpu.state.data_onoff++;
1211+ switch (val&0xf0) {
1212+ case 0xc0:case 0xd0:
1213+ length=mpu.playbuf[mpu.state.track].length=2;
1214+ mpu.playbuf[mpu.state.track].type=T_MIDI_NORM;
1215+ break;
1216+ case 0x80:case 0x90:case 0xa0:case 0xb0:case 0xe0:
1217+ length=mpu.playbuf[mpu.state.track].length=3;
1218+ mpu.playbuf[mpu.state.track].type=T_MIDI_NORM;
1219+ break;
1220+ case 0xf0:
1221+ mpu.playbuf[mpu.state.track].sys_val=val;
1222+ if (val>0xf7) {
1223+ mpu.playbuf[mpu.state.track].type=T_MARK;
1224+ if (val==0xf9) mpu.clock.measure_counter=0;
1225+ } else {
1226+ LOG(LOG_MISC,LOG_WARN)("MPU-401:Illegal message");
1227+ mpu.playbuf[mpu.state.track].type=T_OVERFLOW;
1228+ }
1229+ mpu.state.data_onoff=-1;
1230+ MPU401_EOIHandler();
1231+ mpu.state.track_req=false;
1232+ SDL_mutexV(MPULock);
1233+ return;
1234+ default: /* MIDI with running status */
1235+ cnt++;
1236+ length=mpu.playbuf[mpu.state.track].length;
1237+ mpu.playbuf[mpu.state.track].type=T_MIDI_NORM;
1238 }
1239+ case 2:
1240+ if (cnt<length) {
1241+ mpu.playbuf[mpu.state.track].value[cnt]=val;
1242+ cnt++;
1243+ }
1244+ if (cnt==length) {
1245+ mpu.state.data_onoff=-1;
1246+ mpu.state.track_req=false;
1247+ MPU401_EOIHandlerDispatch();
1248 }
1249- if (!(posd==1 && val>=0xf0)) mpu.playbuf[mpu.state.channel].value[posd-1]=val;
1250- if (posd==length) MPU401_EOIHandlerDispatch();
1251+ break;
1252 }
1253+ SDL_mutexV(MPULock);
1254+ return;
1255 }
1256
1257-static void MPU401_IntelligentOut(Bit8u chan) {
1258- Bitu val;
1259- switch (mpu.playbuf[chan].type) {
1260+static void MPU401_IntelligentOut(Bitu track) {
1261+ Bitu chan,chrefnum;
1262+ Bit8u key,msg;
1263+ bool send,retrigger;
1264+ switch (mpu.playbuf[track].type) {
1265 case T_OVERFLOW:
1266 break;
1267 case T_MARK:
1268- val=mpu.playbuf[chan].sys_val;
1269- if (val==0xfc) {
1270- MIDI_RawOutByte(val);
1271- mpu.state.amask&=~(1<<chan);
1272- mpu.state.req_mask&=~(1<<chan);
1273+ if (mpu.playbuf[track].sys_val==0xfc) {
1274+ MIDI_RawOutRTByte(mpu.playbuf[track].sys_val);
1275+ mpu.state.amask&=~(1<<track);
1276 }
1277 break;
1278 case T_MIDI_NORM:
1279- for (Bitu i=0;i<mpu.playbuf[chan].vlength;i++)
1280- MIDI_RawOutByte(mpu.playbuf[chan].value[i]);
1281- break;
1282- default:
1283- break;
1284+ chan=mpu.playbuf[track].value[0]&0xf;
1285+ key=mpu.playbuf[track].value[1]&0x7f;
1286+ chrefnum=mpu.ch_toref[chan];
1287+ send=true;
1288+ retrigger=false;
1289+ switch (msg=mpu.playbuf[track].value[0]&0xf0) {
1290+ case 0x80: //note off
1291+ if (mpu.inputref[chan].on && (mpu.inputref[chan].M_GETKEY)) send=false;
1292+ if (mpu.chanref[chrefnum].on && (!mpu.chanref[chrefnum].M_GETKEY)) send=false;
1293+ mpu.chanref[chrefnum].M_DELKEY;
1294+ break;
1295+ case 0x90: //note on
1296+ if (mpu.inputref[chan].on && (mpu.inputref[chan].M_GETKEY)) retrigger=true;
1297+ if (mpu.chanref[chrefnum].on && (mpu.chanref[chrefnum].M_GETKEY)) retrigger=true;
1298+ mpu.chanref[chrefnum].M_SETKEY;
1299+ break;
1300+ case 0xb0:
1301+ if (mpu.playbuf[track].value[1]==123) {/* All notes off */
1302+ MPU401_NotesOff(mpu.playbuf[track].value[0]&0xf);
1303+ return;
1304+ }
1305+ break;
1306+ }
1307+ if (retrigger) {
1308+ MIDI_RawOutByte(0x80|chan,MOUT_MPU);
1309+ MIDI_RawOutByte(key,MOUT_MPU);
1310+ MIDI_RawOutByte(0,MOUT_MPU);
1311+ }
1312+ if (send) for (Bitu i=0;i<mpu.playbuf[track].length;i++)
1313+ MIDI_RawOutByte(mpu.playbuf[track].value[i],MOUT_MPU);
1314 }
1315 }
1316
1317-static void UpdateTrack(Bit8u chan) {
1318- MPU401_IntelligentOut(chan);
1319- if (mpu.state.amask&(1<<chan)) {
1320- mpu.playbuf[chan].vlength=0;
1321- mpu.playbuf[chan].type=T_OVERFLOW;
1322- mpu.playbuf[chan].counter=0xf0;
1323- mpu.state.req_mask|=(1<<chan);
1324+static void UpdateTrack(Bit8u track) {
1325+ MPU401_IntelligentOut(track);
1326+ if (mpu.state.amask&(1<<track)) {
1327+ mpu.playbuf[track].type=T_OVERFLOW;
1328+ mpu.playbuf[track].counter=0xf0;
1329+ mpu.state.req_mask|=(1<<track);
1330 } else {
1331 if (mpu.state.amask==0 && !mpu.state.conductor) mpu.state.req_mask|=(1<<12);
1332 }
1333 }
1334
1335-static void UpdateConductor(void) {
1336- for (unsigned int i=0;i < mpu.condbuf.vlength;i++) {
1337- if (mpu.condbuf.value[i] == 0xfc) {
1338- mpu.condbuf.value[i] = 0;
1339- mpu.state.conductor=false;
1340- mpu.state.req_mask&=~(1<<9);
1341- if (mpu.state.amask==0) mpu.state.req_mask|=(1<<12);
1342- return;
1343- }
1344- }
1345-
1346- mpu.condbuf.vlength=0;
1347- mpu.condbuf.counter=0xf0;
1348- mpu.state.req_mask|=(1<<9);
1349-}
1350-
1351 static void MPU401_Event(Bitu val) {
1352 (void)val;//UNUSED
1353 if (mpu.mode==M_UART) return;
1354 if (mpu.state.irq_pending) goto next_event;
1355- for (Bitu i=0;i<8;i++) { /* Decrease counters */
1356- if (mpu.state.amask&(1<<i)) {
1357- mpu.playbuf[i].counter--;
1358- if (mpu.playbuf[i].counter<=0) UpdateTrack(i);
1359- }
1360- }
1361- if (mpu.state.conductor) {
1362- mpu.condbuf.counter--;
1363- if (mpu.condbuf.counter<=0) UpdateConductor();
1364+ if (mpu.state.playing) {
1365+ for (Bitu i=0;i<8;i++) { /* Decrease counters */
1366+ if (mpu.state.amask&(1<<i)) {
1367+ mpu.playbuf[i].counter--;
1368+ if (mpu.playbuf[i].counter<=0) UpdateTrack(i);
1369+ }
1370+ }
1371+ if (mpu.state.conductor) {
1372+ mpu.condbuf.counter--;
1373+ if (mpu.condbuf.counter<=0) {
1374+ mpu.condbuf.counter=0xf0;
1375+ mpu.state.req_mask|=(1<<9);
1376+ }
1377+ }
1378 }
1379- if (mpu.clock.clock_to_host) {
1380+ if (mpu.state.clock_to_host) {
1381 mpu.clock.cth_counter++;
1382- if (mpu.clock.cth_counter >= mpu.clock.cth_rate) {
1383+ if (mpu.clock.cth_counter >= mpu.clock.cth_rate[mpu.clock.cth_mode]) {
1384 mpu.clock.cth_counter=0;
1385+ mpu.clock.cth_mode=(++mpu.clock.cth_mode)%4;
1386 mpu.state.req_mask|=(1<<13);
1387 }
1388 }
1389- if (!mpu.state.irq_pending && mpu.state.req_mask) MPU401_EOIHandler();
1390+ if (mpu.state.rec==M_RECON) { //recording
1391+ mpu.clock.rec_counter++;
1392+ if (mpu.clock.rec_counter>=240) {
1393+ mpu.clock.rec_counter=0;
1394+ mpu.state.req_mask|=(1<<8);
1395+ }
1396+ }
1397+ bool accented;
1398+ if (mpu.state.playing || mpu.state.rec==M_RECON) {
1399+ accented=false;
1400+ Bits max_meascnt = (mpu.clock.timebase*mpu.clock.midimetro*mpu.clock.metromeas)/24;
1401+ if (max_meascnt!=0) { //measure end
1402+ if (++mpu.clock.measure_counter>=max_meascnt) {
1403+ if (mpu.filter.rt_out) MIDI_RawOutRTByte(0xf8);
1404+ mpu.clock.measure_counter=0;
1405+ if (mpu.filter.rec_measure_end && mpu.state.rec==M_RECON)
1406+ mpu.state.req_mask|=(1<<12);
1407+ }
1408+ }
1409+ }
1410+ if (!mpu.state.irq_pending && mpu.state.req_mask) {
1411+ SDL_mutexP(MPULock);
1412+ MPU401_EOIHandler();
1413+ SDL_mutexV(MPULock);
1414+ }
1415 next_event:
1416- Bitu new_time;
1417- if ((new_time=(Bitu)((mpu.clock.tempo*mpu.clock.timebase*mpu.clock.tempo_rel)/0x40))==0) return;
1418- PIC_AddEvent(MPU401_Event,MPU401_TIMECONSTANT/new_time);
1419+ MPU401_RunClock();
1420+ if (mpu.state.sync_in) mpu.clock.ticks_in++;
1421 }
1422
1423
1424@@ -585,15 +951,19 @@ static void MPU401_EOIHandler(Bitu val)
1425 mpu.state.eoi_scheduled=false;
1426 if (mpu.state.send_now) {
1427 mpu.state.send_now=false;
1428- if (mpu.state.cond_req) UpdateConductor();
1429- else UpdateTrack(mpu.state.channel);
1430+ if (mpu.state.cond_req) {
1431+ mpu.condbuf.counter=0xf0;
1432+ mpu.state.req_mask|=(1<<9);
1433+ }
1434+ else UpdateTrack(mpu.state.track);
1435 }
1436+ if (mpu.state.rec_copy || !mpu.state.sysex_in_finished) return;
1437 mpu.state.irq_pending=false;
1438- if (!mpu.state.playing || !mpu.state.req_mask) return;
1439+ if (!(mpu.state.req_mask && mpu.clock.active)) return;
1440 Bitu i=0;
1441 do {
1442 if (mpu.state.req_mask&(1<<i)) {
1443- QueueByte(0xf0+i);
1444+ MPU401_QueueByte(0xf0+i);
1445 mpu.state.req_mask&=~(1<<i);
1446 break;
1447 }
1448@@ -607,43 +977,287 @@ static void MPU401_ResetDone(Bitu) {
1449 mpu.state.cmd_pending=0;
1450 }
1451 }
1452+
1453+static INLINE void MPU401_NotesOff(Bitu i) {
1454+ if (mpu.filter.allnotesoff_out && !(mpu.inputref[i].on &&
1455+ (mpu.inputref[i].key[0]|mpu.inputref[i].key[1]|
1456+ mpu.inputref[i].key[2]|mpu.inputref[i].key[3]))) {
1457+ for (Bitu j=0;j<4;j++) mpu.chanref[mpu.ch_toref[i]].key[j]=0;
1458+ //if (mpu.chanref[mpu.ch_toref[i]].on) {
1459+ MIDI_RawOutByte(0xb0|i,MOUT_MPU);
1460+ MIDI_RawOutByte(123,MOUT_MPU);
1461+ MIDI_RawOutByte(0,MOUT_MPU);
1462+ }
1463+ else if (mpu.chanref[mpu.ch_toref[i]].on)
1464+ for (Bitu key=0;key<128;key++) {
1465+ if ((mpu.chanref[mpu.ch_toref[i]].M_GETKEY) &&
1466+ !(mpu.inputref[i].on && (mpu.inputref[i].M_GETKEY))) {
1467+ MIDI_RawOutByte(0x80|i,MOUT_MPU);
1468+ MIDI_RawOutByte(key,MOUT_MPU);
1469+ MIDI_RawOutByte(0,MOUT_MPU);
1470+ }
1471+ mpu.chanref[mpu.ch_toref[i]].M_DELKEY;
1472+ }
1473+}
1474+
1475+//Input handler for SysEx
1476+Bits MPU401_InputSysex(Bit8u* buffer,Bitu len,bool abort) {
1477+ if (mpu.filter.sysex_in) {
1478+ if (abort) {
1479+ mpu.state.sysex_in_finished=true;
1480+ mpu.rec_queue_used=0;//reset also the input queue
1481+ return 0;
1482+ }
1483+ if (mpu.state.sysex_in_finished) {
1484+ if (mpu.rec_queue_used>=MPU401_INPUT_QUEUE) return len;
1485+ Bit8u val_ff=0xff;
1486+ MPU401_RecQueueBuffer(&val_ff,1,true);
1487+ mpu.state.sysex_in_finished=false;
1488+ mpu.clock.rec_counter=0;
1489+ }
1490+ if (mpu.rec_queue_used>=MPU401_INPUT_QUEUE) return len;
1491+ Bitu available=MPU401_INPUT_QUEUE-mpu.rec_queue_used;
1492+
1493+ if (available>=len) {
1494+ MPU401_RecQueueBuffer(buffer,len,true);
1495+ return 0;
1496+ }
1497+ else {
1498+ MPU401_RecQueueBuffer(buffer,available,true);
1499+ if (mpu.state.sysex_in_finished) return 0;
1500+ return (len-available);
1501+ }
1502+ }
1503+ else if (mpu.filter.sysex_thru && mpuhw.midi_thru) {
1504+ MIDI_RawOutByte(0xf0,MOUT_THRU);
1505+ for (Bitu i=0;i<len;i++) MIDI_RawOutByte(*(buffer+i),MOUT_THRU);
1506+ }
1507+ return 0;
1508+}
1509+
1510+//Input handler for MIDI
1511+void MPU401_InputMsg(Bit8u msg[4]) {
1512+ //abort if sysex transfer is in progress
1513+ if (!mpu.state.sysex_in_finished) return;
1514+ static Bit8u old_msg=0;
1515+ Bit8u len=msg[3];
1516+ bool send=true;
1517+ bool send_thru=false;
1518+ bool retrigger_thru=false;
1519+ bool midistatus=false;
1520+ if (mpu.mode==M_INTELLIGENT) {
1521+ if (msg[0]<0x80) { // Expand running status
1522+ midistatus=true;
1523+ msg[2]=msg[1];msg[1]=msg[0];msg[0]=old_msg;
1524+ }
1525+ old_msg=msg[0];
1526+ Bitu chan=msg[0]&0xf;
1527+ Bitu chrefnum=mpu.ch_toref[chan];
1528+ Bit8u key=msg[1]&0x7f;
1529+ if (msg[0]<0xf0) { //if non-system msg
1530+ if (!(mpu.state.midi_mask&(1<<chan)) && mpu.filter.all_thru) send_thru=true;
1531+ else if (mpu.filter.midi_thru) send_thru=true;
1532+ switch (msg[0]&0xf0) {
1533+ case 0x80: //note off
1534+ if (send_thru) {
1535+ if (mpu.chanref[chrefnum].on && (mpu.chanref[chrefnum].M_GETKEY))
1536+ send_thru=false;
1537+ if (!mpu.filter.midi_thru) break;
1538+ if (!(mpu.inputref[chan].M_GETKEY)) send_thru=false;
1539+ mpu.inputref[chan].M_DELKEY;
1540+ }
1541+ break;
1542+ case 0x90: //note on
1543+ if (send_thru) {
1544+ if (mpu.chanref[chrefnum].on && (mpu.chanref[chrefnum].M_GETKEY))
1545+ retrigger_thru=true;
1546+ if (!mpu.filter.midi_thru) break;
1547+ if (mpu.inputref[chan].M_GETKEY) retrigger_thru=true;
1548+ mpu.inputref[chan].M_SETKEY;
1549+ }
1550+ break;
1551+ case 0xb0:
1552+ if (msg[1]>=120) {
1553+ send_thru=false;
1554+ if (msg[1]==123) /* All notes off */
1555+ for (key=0;key<128;key++) {
1556+ if (!(mpu.chanref[chrefnum].on && (mpu.chanref[chrefnum].M_GETKEY)))
1557+ if (mpu.inputref[chan].on && mpu.inputref[chan].M_GETKEY) {
1558+ MIDI_RawOutByte(0x80|chan,MOUT_THRU);
1559+ MIDI_RawOutByte(key,MOUT_THRU);
1560+ MIDI_RawOutByte(0,MOUT_THRU);
1561+ }
1562+ mpu.inputref[chan].M_DELKEY;
1563+ }
1564+ }
1565+ break;
1566+ }
1567+ }
1568+ if (msg[0]>=0xf0 || (mpu.state.midi_mask&(1<<chan)))
1569+ switch (msg[0]&0xf0) {
1570+ case 0xa0: //aftertouch
1571+ if (!mpu.filter.bender_in) send=false;
1572+ break;
1573+ case 0xb0: //control change
1574+ if (!mpu.filter.bender_in && msg[1]<64) send=false;
1575+ if (msg[1]>=120) if (mpu.filter.modemsgs_in) send=true;
1576+ break;
1577+ case 0xc0: //program change
1578+ if (mpu.state.rec!=M_RECON && !mpu.filter.data_in_stop) {
1579+ mpu.filter.prchg_buf[chan]=msg[1];
1580+ mpu.filter.prchg_mask|=1<<chan;
1581+ }
1582+ break;
1583+ case 0xd0: //ch pressure
1584+ case 0xe0: //pitch wheel
1585+ if (!mpu.filter.bender_in) send=false;
1586+ break;
1587+ case 0xf0: //system message
1588+ if (msg[0]==0xf8) {
1589+ send=false;
1590+ if (mpu.clock.active && mpu.state.sync_in) {
1591+ send = false;//don't pass to host in this mode?
1592+ Bits tick=mpu.clock.timebase/24;
1593+ if (mpu.clock.ticks_in!=tick) {
1594+ if (!mpu.clock.ticks_in || mpu.clock.ticks_in>tick*2) mpu.clock.freq_mod*=2.0;
1595+ else {
1596+ if (abs(mpu.clock.ticks_in-tick)==1)
1597+ mpu.clock.freq_mod/=mpu.clock.ticks_in/float(tick*2);
1598+ else
1599+ mpu.clock.freq_mod/=mpu.clock.ticks_in/float(tick);
1600+ }
1601+ MPU401_ReCalcClock();
1602+ }
1603+ mpu.clock.ticks_in=0;
1604+ }
1605+ }
1606+ else if (msg[0]>0xf8) { //realtime
1607+ if (!(mpu.filter.rt_in && msg[0]<=0xfc && msg[0]>=0xfa)) {
1608+ Bit8u recdata[2]={0xff,msg[0]};
1609+ MPU401_RecQueueBuffer(recdata,2,true);
1610+ send=false;
1611+ }
1612+ }
1613+ else { //common or system
1614+ send=false;
1615+ if (msg[0]==0xf2 || msg[0]==0xf3 || msg[0]==0xf6) {
1616+ if (mpu.filter.commonmsgs_in) send=true;
1617+ if (mpu.filter.commonmsgs_thru)
1618+ for (Bitu i=0;i<len;i++) MIDI_RawOutByte(msg[i],MOUT_THRU);
1619+ }
1620+ }
1621+ if (send) {
1622+ Bit8u recmsg[4]={0xff,msg[0],msg[1],msg[2]};
1623+ MPU401_RecQueueBuffer(recmsg,len+1,true);
1624+ }
1625+ if (mpu.filter.rt_affection) switch(msg[0]) {
1626+ case 0xf2:case 0xf3:
1627+ mpu.state.block_ack=true;
1628+ MPU401_WriteCommand(0x331,0xb8,1);//clear play counters
1629+ break;
1630+ case 0xfa:
1631+ mpu.state.block_ack=true;
1632+ MPU401_WriteCommand(0x331,0xa,1);//start,play
1633+ if (mpu.filter.rt_out) MIDI_RawOutThruRTByte(msg[0]);
1634+ break;
1635+ case 0xfb:
1636+ mpu.state.block_ack=true;
1637+ MPU401_WriteCommand(0x331,0xb,1);//continue,play
1638+ if (mpu.filter.rt_out) MIDI_RawOutThruRTByte(msg[0]);
1639+ break;
1640+ case 0xfc:
1641+ mpu.state.block_ack=true;
1642+ MPU401_WriteCommand(0x331,0xd,1);//stop: play,rec,midi
1643+ if (mpu.filter.rt_out) MIDI_RawOutThruRTByte(msg[0]);
1644+ break;
1645+ }
1646+ return;
1647+ }
1648+ if (send_thru && mpuhw.midi_thru) {
1649+ if (retrigger_thru) {
1650+ MIDI_RawOutByte(0x80|(msg[0]&0xf),MOUT_THRU);
1651+ MIDI_RawOutByte(msg[1],MOUT_THRU);
1652+ MIDI_RawOutByte(msg[2],MOUT_THRU);
1653+ }
1654+ for (Bitu i=0/*((midistatus && !retrigger_thru)? 1:0)*/;i<len;i++)
1655+ MIDI_RawOutByte(msg[i],MOUT_THRU);
1656+ }
1657+ if (send) {
1658+ if (mpu.state.rec==M_RECON) {
1659+ Bit8u recmsg[4]={mpu.clock.rec_counter,msg[0],msg[1],msg[2]};
1660+ MPU401_RecQueueBuffer(recmsg,len+1,true);
1661+ mpu.clock.rec_counter=0;
1662+ }
1663+ else if (mpu.filter.data_in_stop) {
1664+ if (mpu.filter.timing_in_stop) {
1665+ Bit8u recmsg[4]={0,msg[0],msg[1],msg[2]};
1666+ MPU401_RecQueueBuffer(recmsg,len+1,true);
1667+ }
1668+ else {
1669+ Bit8u recmsg[4]={msg[0],msg[1],msg[2],0};
1670+ MPU401_RecQueueBuffer(recmsg,len,true);
1671+ }
1672+ }
1673+ }
1674+ return;
1675+ }
1676+ //UART mode input
1677+ for (Bitu i=0;i<len;i++) MPU401_QueueByte(msg[i]);
1678+}
1679+
1680 static void MPU401_Reset(void) {
1681- PIC_DeActivateIRQ(mpu.irq);
1682- mpu.mode=(mpu.intelligent ? M_INTELLIGENT : M_UART);
1683 PIC_RemoveEvents(MPU401_EOIHandler);
1684 mpu.state.eoi_scheduled=false;
1685- mpu.state.wsd=false;
1686- mpu.state.wsm=false;
1687- mpu.state.conductor=false;
1688- mpu.state.cond_req=false;
1689- mpu.state.cond_set=false;
1690- mpu.state.playing=false;
1691- mpu.state.run_irq=false;
1692+ PIC_DeActivateIRQ(mpuhw.irq);
1693 mpu.state.irq_pending=false;
1694- mpu.state.cmask=0xff;
1695- mpu.state.amask=mpu.state.tmask=0;
1696+ memset(&mpu,0,sizeof(mpu));
1697+ mpu.mode=(mpuhw.intelligent ? M_INTELLIGENT : M_UART);
1698+ mpuhw.midi_thru=false;
1699+ mpu.state.rec=M_RECOFF;
1700 mpu.state.midi_mask=0xffff;
1701- mpu.state.data_onoff=0;
1702- mpu.state.command_byte=0;
1703- mpu.state.block_ack=false;
1704 mpu.clock.tempo=mpu.clock.old_tempo=100;
1705 mpu.clock.timebase=mpu.clock.old_timebase=120;
1706 mpu.clock.tempo_rel=mpu.clock.old_tempo_rel=0x40;
1707- mpu.clock.tempo_grad=0;
1708- mpu.clock.clock_to_host=false;
1709- mpu.clock.cth_rate=60;
1710- mpu.clock.cth_counter=0;
1711- ClrQueue();
1712- mpu.state.req_mask=0;
1713- mpu.condbuf.counter=0;
1714+ mpu.clock.freq_mod=1.0;
1715+ MPU401_StopClock();
1716+ MPU401_ReCalcClock();
1717+ for (Bitu i=0;i<4;i++) mpu.clock.cth_rate[i]=60;
1718+ mpu.clock.midimetro=12;
1719+ mpu.clock.metromeas=8;
1720+ mpu.filter.rec_measure_end=true;
1721+ mpu.filter.rt_out=true;
1722+ mpu.filter.rt_affection=true;
1723+ mpu.filter.allnotesoff_out=true;
1724+ mpu.filter.all_thru=true;
1725+ mpu.filter.midi_thru=true;
1726+ mpu.filter.commonmsgs_thru=true;
1727+ //reset channel reference and input tables
1728+ for (Bitu i=0;i<4;i++) {
1729+ mpu.chanref[i].on=true;
1730+ mpu.chanref[i].chan=i;
1731+ mpu.ch_toref[i]=i;
1732+ }
1733+ for (Bitu i=0;i<16;i++) {
1734+ mpu.inputref[i].on=true;
1735+ mpu.inputref[i].chan=i;
1736+ if (i>3) mpu.ch_toref[i]=4;//dummy reftable
1737+ }
1738+ MPU401_ClrQueue();
1739+ mpu.state.data_onoff=-1;
1740 mpu.condbuf.type=T_OVERFLOW;
1741- for (Bitu i=0;i<8;i++) {mpu.playbuf[i].type=T_OVERFLOW;mpu.playbuf[i].counter=0;}
1742+ for (Bitu i=0;i<8;i++) mpu.playbuf[i].type=T_OVERFLOW;
1743+ //clear MIDI buffers, terminate notes
1744+ MIDI_ClearBuffer(MOUT_MPU);
1745+ MIDI_ClearBuffer(MOUT_THRU);
1746+ for (Bitu i=0xb0;i<=0xbf;i++){
1747+ MIDI_RawOutByte(i,MOUT_MPU);
1748+ MIDI_RawOutByte(0x7b,MOUT_MPU);
1749+ MIDI_RawOutByte(0,MOUT_MPU);
1750+ }
1751 }
1752
1753 class MPU401:public Module_base{
1754 private:
1755- IO_ReadHandleObject ReadHandler[2];
1756- IO_WriteHandleObject WriteHandler[2];
1757 bool installed; /*as it can fail to install by 2 ways (config and no midi)*/
1758 public:
1759 MPU401(Section* configuration):Module_base(configuration){
1760@@ -657,28 +1271,34 @@ public:
1761 /*Enabled and there is a Midi */
1762 installed = true;
1763
1764- WriteHandler[0].Install(0x330,&MPU401_WriteData,IO_MB);
1765- WriteHandler[1].Install(0x331,&MPU401_WriteCommand,IO_MB);
1766- ReadHandler[0].Install(0x330,&MPU401_ReadData,IO_MB);
1767- ReadHandler[1].Install(0x331,&MPU401_ReadStatus,IO_MB);
1768+ MPULock=SDL_CreateMutex();
1769+
1770+ mpuhw.WriteHandler[0].Install(0x330,&MPU401_WriteData,IO_MB);
1771+ mpuhw.WriteHandler[1].Install(0x331,&MPU401_WriteCommand,IO_MB);
1772+ mpuhw.ReadHandler[0].Install(0x330,&MPU401_ReadData,IO_MB);
1773+ mpuhw.ReadHandler[1].Install(0x331,&MPU401_ReadStatus,IO_MB);
1774
1775 mpu.queue_used=0;
1776 mpu.queue_pos=0;
1777+ mpu.state.irq_pending=false;
1778 mpu.mode=M_UART;
1779- mpu.irq=9; /* Princess Maker 2 wants it on irq 9 */
1780+ mpuhw.irq=9; /* Princess Maker 2 wants it on irq 9 */
1781
1782- mpu.intelligent = true; //Default is on
1783- if(strcasecmp(s_mpu,"uart") == 0) mpu.intelligent = false;
1784- if (!mpu.intelligent) return;
1785+ mpuhw.intelligent = true; //Default is on
1786+ if(strcasecmp(s_mpu,"uart") == 0) mpuhw.intelligent = false;
1787+ if (!mpuhw.intelligent) return;
1788 /*Set IRQ and unmask it(for timequest/princess maker 2) */
1789- PIC_SetIRQMask(mpu.irq,false);
1790+ PIC_SetIRQMask(mpuhw.irq,false);
1791 MPU401_Reset();
1792 }
1793 ~MPU401(){
1794 if(!installed) return;
1795+ PIC_RemoveEvents(MPU401_Event);
1796+ SDL_DestroyMutex(MPULock);
1797+ MPULock=0;
1798 Section_prop * section=static_cast<Section_prop *>(m_configuration);
1799 if(strcasecmp(section->Get_string("mpu401"),"intelligent")) return;
1800- PIC_SetIRQMask(mpu.irq,true);
1801+ PIC_SetIRQMask(mpuhw.irq,true);
1802 }
1803 };
1804