1
0
Fork 0

Several fixes for regressions (Innocent until caught and curse of enchantia), Add fix for mechwarrior.)

lowered eoi timeout to 0.06f. (ripsaw, Srecko and h-a-l-9000)

Imported-from: https://svn.code.sf.net/p/dosbox/code-0/dosbox/trunk@3791
This commit is contained in:
Peter Veenstra 2012-08-11 17:40:32 +00:00
parent 41729e0ca5
commit d95950242d

View file

@ -1,5 +1,5 @@
/*
* Copyright (C) 2002-2011 The DOSBox Team
* Copyright (C) 2002-2012 The DOSBox Team
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
@ -30,12 +30,15 @@ bool MIDI_Available(void);
static void MPU401_Event(Bitu);
static void MPU401_Reset(void);
static void MPU401_EOIHandler(void);
static void MPU401_ResetDone(Bitu);
static void MPU401_EOIHandler(Bitu val=0);
static void MPU401_EOIHandlerDispatch(void);
#define MPU401_VERSION 0x15
#define MPU401_REVISION 0x01
#define MPU401_QUEUE 32
#define MPU401_TIMECONSTANT (60000000/1000.0f)
#define MPU401_RESETBUSY 27.0f
enum MpuMode { M_UART,M_INTELLIGENT };
enum MpuDataType {T_OVERFLOW,T_MARK,T_MIDI_SYS,T_MIDI_NORM,T_COMMAND};
@ -72,8 +75,9 @@ static struct {
bool wsd,wsm,wsd_start;
bool run_irq,irq_pending;
bool send_now;
bool eoi_scheduled;
Bits data_onoff;
Bitu command_byte;
Bitu command_byte,cmd_pending;
Bit8u tmask,cmask,amask;
Bit16u midi_mask;
Bit16u req_mask;
@ -112,12 +116,13 @@ static void ClrQueue(void) {
static Bitu MPU401_ReadStatus(Bitu port,Bitu iolen) {
Bit8u ret=0x3f; /* Bits 6 and 7 clear */
if (mpu.state.cmd_pending) ret|=0x40;
if (!mpu.queue_used) ret|=0x80;
return ret;
}
static void MPU401_WriteCommand(Bitu port,Bitu val,Bitu iolen) {
mpu.state.reset=0;
if (mpu.state.reset) {mpu.state.cmd_pending=val+1;return;}
if (val<=0x2f) {
switch (val&3) { /* MIDI stop, start, continue */
case 1: {MIDI_RawOutByte(0xfc);break;}
@ -239,12 +244,10 @@ static void MPU401_WriteCommand(Bitu port,Bitu val,Bitu iolen) {
break;
case 0xff: /* Reset MPU-401 */
LOG(LOG_MISC,LOG_NORMAL)("MPU-401:Reset %X",val);
mpu.state.reset=1;
if (CPU_Cycles > 5) { //It came from the desert wants a fast irq
CPU_CycleLeft += CPU_Cycles;
CPU_Cycles = 5;
}
PIC_AddEvent(MPU401_ResetDone,MPU401_RESETBUSY);
mpu.state.reset=true;
MPU401_Reset();
if (mpu.mode==M_UART) return;//do not send ack in UART mode
break;
case 0x3f: /* UART mode */
LOG(LOG_MISC,LOG_NORMAL)("MPU-401:Set UART mode %X",val);
@ -284,7 +287,7 @@ static Bitu MPU401_ReadData(Bitu port,Bitu iolen) {
}
if (ret==MSG_MPU_END || ret==MSG_MPU_CLOCK || ret==MSG_MPU_ACK) {
mpu.state.data_onoff=-1;
MPU401_EOIHandler();
MPU401_EOIHandlerDispatch();
}
return ret;
}
@ -390,7 +393,7 @@ static void MPU401_WriteData(Bitu port,Bitu val,Bitu iolen) {
if (val<0xf0) mpu.state.data_onoff++;
else {
mpu.state.data_onoff=-1;
MPU401_EOIHandler();
MPU401_EOIHandlerDispatch();
return;
}
if (val==0) mpu.state.send_now=true;
@ -402,13 +405,13 @@ static void MPU401_WriteData(Bitu port,Bitu val,Bitu iolen) {
if (val==0xf8 || val==0xf9) mpu.condbuf.type=T_OVERFLOW;
mpu.condbuf.value[mpu.condbuf.vlength]=val;
mpu.condbuf.vlength++;
if ((val&0xf0)!=0xe0) MPU401_EOIHandler();
if ((val&0xf0)!=0xe0) MPU401_EOIHandlerDispatch();
else mpu.state.data_onoff++;
break;
case 2:/* Command byte #2 */
mpu.condbuf.value[mpu.condbuf.vlength]=val;
mpu.condbuf.vlength++;
MPU401_EOIHandler();
MPU401_EOIHandlerDispatch();
break;
}
return;
@ -420,7 +423,7 @@ static void MPU401_WriteData(Bitu port,Bitu val,Bitu iolen) {
if (val<0xf0) mpu.state.data_onoff=1;
else {
mpu.state.data_onoff=-1;
MPU401_EOIHandler();
MPU401_EOIHandlerDispatch();
return;
}
if (val==0) mpu.state.send_now=true;
@ -461,7 +464,7 @@ static void MPU401_WriteData(Bitu port,Bitu val,Bitu iolen) {
}
}
if (!(posd==1 && val>=0xf0)) mpu.playbuf[mpu.state.channel].value[posd-1]=val;
if (posd==length) MPU401_EOIHandler();
if (posd==length) MPU401_EOIHandlerDispatch();
}
}
@ -540,7 +543,18 @@ next_event:
PIC_AddEvent(MPU401_Event,MPU401_TIMECONSTANT/new_time);
}
static void MPU401_EOIHandler(void) {
static void MPU401_EOIHandlerDispatch(void) {
if (mpu.state.send_now) {
mpu.state.eoi_scheduled=true;
PIC_AddEvent(MPU401_EOIHandler,0.06f); //Possible a bit longer
}
else if (!mpu.state.eoi_scheduled) MPU401_EOIHandler();
}
//Updates counters and requests new data on "End of Input"
static void MPU401_EOIHandler(Bitu val) {
mpu.state.eoi_scheduled=false;
if (mpu.state.send_now) {
mpu.state.send_now=false;
if (mpu.state.cond_req) UpdateConductor();
@ -558,9 +572,18 @@ static void MPU401_EOIHandler(void) {
} while ((i++)<16);
}
static void MPU401_ResetDone(Bitu) {
mpu.state.reset=false;
if (mpu.state.cmd_pending) {
MPU401_WriteCommand(0x331,mpu.state.cmd_pending-1,1);
mpu.state.cmd_pending=0;
}
}
static void MPU401_Reset(void) {
PIC_DeActivateIRQ(mpu.irq);
mpu.mode=(mpu.intelligent ? M_INTELLIGENT : M_UART);
PIC_RemoveEvents(MPU401_EOIHandler);
mpu.state.eoi_scheduled=false;
mpu.state.wsd=false;
mpu.state.wsm=false;
mpu.state.conductor=false;