From dc8179439a1c63c5bb81e8f3d9eedb6194319647 Mon Sep 17 00:00:00 2001 From: Peter Veenstra Date: Thu, 18 Mar 2004 16:21:04 +0000 Subject: [PATCH] Additions to mp401 suggested by Screcko. Legend games are now working. Imported-from: https://svn.code.sf.net/p/dosbox/code-0/dosbox/trunk@1732 --- src/hardware/mpu401.cpp | 225 ++++++++++++++++++++++++---------------- 1 file changed, 138 insertions(+), 87 deletions(-) diff --git a/src/hardware/mpu401.cpp b/src/hardware/mpu401.cpp index 409adb97..1c3662b0 100644 --- a/src/hardware/mpu401.cpp +++ b/src/hardware/mpu401.cpp @@ -15,11 +15,10 @@ static void MPU401_Reset(void); static void MPU401_EOIHandler(void); #define MPU_QUEUE 32 -#define MPU_RQ_QUEUE 64 #define TIMECONSTANT 60000000 enum MpuMode { M_UART,M_INTELLIGENT } ; -enum MpuDataType {UNSET,OVERFLOW,MARK,MIDI_SYS,MIDI_NORM,MIDI_DATA,COMMAND}; +enum MpuDataType {OVERFLOW,MARK,MIDI_SYS,MIDI_NORM,COMMAND}; ///////////////////////////////////////////////////////////////////////////// // I/O @@ -168,10 +167,10 @@ static struct { Bitu irq; Bit8u queue[MPU_QUEUE]; Bitu queue_pos,queue_used; - struct type_t{ + struct track { Bits counter; Bit8u value[8]; - Bit8u vlength; + Bit8u vlength,length; MpuDataType type; } playbuf[8],condbuf; struct { @@ -181,6 +180,7 @@ static struct { bool wsd,wsm,wsd_start; bool midi_thru; bool run_irq,irq_pending; + bool send_now; Bits data_onoff; Bitu command_byte; Bit8u tmask,cmask,amask; @@ -233,6 +233,11 @@ static void MPU401_WriteCommand(Bit32u port,Bit8u val) { case 0x4: /* Stop */ PIC_RemoveEvents(MPU401_Event); mpu.state.playing=false; + for (Bitu i=0xb0;i<0xbf;i++) {//All notes off + MIDI_RawOutByte(i); + MIDI_RawOutByte(0x7b); + MIDI_RawOutByte(0); + } ClrQueue(); break; case 0x8: /* Play */ @@ -248,7 +253,6 @@ static void MPU401_WriteCommand(Bit32u port,Bit8u val) { } else if (val>=0xd0 && val<=0xd7) { /* Request to send data */ mpu.state.channel=val&7; - //if (!mpu.playbuf[mpu.state.channel].active) mpu.state.wsd=true; mpu.state.wsm=false; mpu.state.wsd_start=true; @@ -347,7 +351,7 @@ static void MPU401_WriteCommand(Bit32u port,Bit8u val) { } for (Bitu i=0;i<8;i++) { mpu.playbuf[i].counter=0; - mpu.playbuf[i].type=UNSET; + mpu.playbuf[i].type=OVERFLOW; } mpu.condbuf.counter=0; mpu.condbuf.type=OVERFLOW; @@ -377,7 +381,7 @@ static void MPU401_WriteCommand(Bit32u port,Bit8u val) { mpu.state.allthru=false; break; default: - LOG(LOG_MISC,LOG_NORMAL)("MPU401:Unhandled command %X",val); + LOG(LOG_MISC,LOG_NORMAL)("MPU-401:Unhandled command %X",val); } QueueByte(MSG_CMD_ACK); } @@ -393,21 +397,21 @@ static Bit8u MPU401_ReadData(Bit32u port) { mpu.state.channel=ret&7; mpu.state.data_onoff=0; mpu.state.cond_req=false; - mpu.playbuf[mpu.state.channel].counter=0; } if (ret==MSG_REQUEST_COMMAND) { mpu.state.data_onoff=0; mpu.state.cond_req=true; - mpu.condbuf.counter=0; } if (ret==MSG_ALL_END || ret==MSG_CLOCK_TO_HOST) { mpu.state.data_onoff=-1; + MPU401_EOIHandler(); } return ret; } static void MPU401_WriteData(Bit32u port,Bit8u val) { if (mpu.mode==M_UART) {MIDI_RawOutByte(val);return;} + if (mpu.state.command_byte) MPU401_EOIHandler(); /* S101, Time Quest */ switch (mpu.state.command_byte) { case 0: break; @@ -445,22 +449,28 @@ static void MPU401_WriteData(Bit32u port,Bit8u val) { mpu.state.command_byte=0; return; } - static Bitu length,cnt; + static Bitu length,cnt,posd; if (mpu.state.wsd) { if (mpu.state.wsd_start) { mpu.state.wsd_start=0; cnt=0; - switch (val&0xf0) { - case 0xc0: - case 0xd0: - length=2; - break; - case 0xf0: - if (!mpu.state.allthru) {mpu.state.wsd=0;return;} - else {length=1;break;} - default: - length=3; - } + switch (val&0xf0) { + case 0xc0:case 0xd0: + mpu.playbuf[mpu.state.channel].value[0]=val; + length=2; + break; + case 0x80:case 0x90:case 0xa0:case 0xb0:case 0xe0: + mpu.playbuf[mpu.state.channel].value[0]=val; + length=3; + break; + case 0xf0: + LOG(LOG_MISC,LOG_ERROR)("MPU-401:Illegal WSD byte"); + mpu.state.wsd=0; + return; + default: /* MIDI with running status */ + cnt++; + MIDI_RawOutByte(mpu.playbuf[mpu.state.channel].value[0]); + } } if (cnt8) return; - mpu.playbuf[mpu.state.channel].value[posd-1]=val; + posd=mpu.playbuf[mpu.state.channel].vlength; if (posd==1) { switch (val&0xf0) { - case 0xf0: - mpu.playbuf[mpu.state.channel].type=(val>0xf7 ? MARK : MIDI_SYS); + case 0xf0: /* System message or mark */ + if (val>0xf7) { + mpu.playbuf[mpu.state.channel].type=MARK; + length=1; + } else { + LOG(LOG_MISC,LOG_ERROR)("MPU-401:Illegal message"); + mpu.playbuf[mpu.state.channel].type=MIDI_SYS; + length=1; + } break; - case 0xe0: case 0xd0: case 0xc0: case 0xb0: case 0xa0: case 0x90: case 0x80: + case 0xc0: case 0xd0: /* MIDI Message */ mpu.playbuf[mpu.state.channel].type=MIDI_NORM; + length=mpu.playbuf[mpu.state.channel].length=2; + break; + case 0x80: case 0x90: case 0xa0: case 0xb0: case 0xe0: + mpu.playbuf[mpu.state.channel].type=MIDI_NORM; + length=mpu.playbuf[mpu.state.channel].length=3; + break; + default: /* MIDI data with running status */ + posd++; + mpu.playbuf[mpu.state.channel].vlength++; + mpu.playbuf[mpu.state.channel].type=MIDI_NORM; + length=mpu.playbuf[mpu.state.channel].length; break; - default: - mpu.playbuf[mpu.state.channel].type=MIDI_DATA; } } + mpu.playbuf[mpu.state.channel].value[posd-1]=val; + if (posd==length) MPU401_EOIHandler(); } } static void MPU401_IntelligentOut(Bit8u chan) { Bitu val; switch (mpu.playbuf[chan].type) { - case UNSET: case OVERFLOW: break; case MARK: val=mpu.playbuf[chan].value[0]; - if (val==0xfc) {MIDI_RawOutByte(val);mpu.state.amask&=~(1<=500) { + CPU_CycleLeft+=CPU_Cycles-500; + CPU_Cycles=500; + } #endif PIC_ActivateIRQ(mpu.irq); mpu.state.irq_pending=true; @@ -630,7 +681,6 @@ static void MPU401_EOIHandler(void) static Bitu INT71_Handler() { CALLBACK_RunRealInt(0xa); IO_Write(0xa0,0x61); - MPU401_EOIHandler(); return CBRET_NONE; } @@ -653,7 +703,7 @@ static void MPU401_Reset(void) { mpu.state.midi_mask=0xffff; mpu.state.data_onoff=0; mpu.state.command_byte=0; - mpu.clock.tempo=mpu.clock.old_tempo=160; + mpu.clock.tempo=mpu.clock.old_tempo=100; mpu.clock.timebase=mpu.clock.old_timebase=120; mpu.clock.tempo_rel=mpu.clock.old_tempo_rel=40; mpu.clock.tempo_grad=0; @@ -664,10 +714,14 @@ static void MPU401_Reset(void) { mpu.state.req_mask=0; mpu.condbuf.counter=0; mpu.condbuf.type=OVERFLOW; - for (Bitu i=0;i<8;i++) {mpu.playbuf[i].type=UNSET;mpu.playbuf[i].counter=0;} + for (Bitu i=0;i<8;i++) {mpu.playbuf[i].type=OVERFLOW;mpu.playbuf[i].counter=0;} } void MPU401_Init(Section* sec) { + call_irq9=CALLBACK_Allocate(); //allocate handler for irq 9 + CALLBACK_Setup(call_irq9,&INT71_Handler,CB_IRET); + RealSetVec(0x71,CALLBACK_RealPointer(call_irq9)); + Section_prop * section=static_cast(sec); if(!section->Get_bool("mpu401")) return; @@ -685,8 +739,5 @@ void MPU401_Init(Section* sec) { if (!(mpu.intelligent=section->Get_bool("intelligent"))) return; mpu.irq=2; PIC_RegisterIRQ(mpu.irq,0,"MPU401"); - call_irq9=CALLBACK_Allocate(); //allocate handler for irq 9 - CALLBACK_Setup(call_irq9,&INT71_Handler,CB_IRET); - RealSetVec(0x71,CALLBACK_RealPointer(call_irq9)); MPU401_Reset(); }