void init (VM32Cpu * cpu) { VMReset(cpu); cpu->breakHook = DefaultBreak; cpu->invalidHook = DefaultInvalidInstruction; cpu->argCountHook = DefaultInvalidArgCount; cpu->pushHook = NULL; cpu->activateHook = NULL; }
/*---------------------------------------------------------------------------- * ProcessSysExMessage() *---------------------------------------------------------------------------- * Purpose: * Process a SysEx character byte from the MIDI stream. Since we cannot * simply wait for the next character to arrive, we are forced to save * state after each character. It would be easier to parse at the file * level, but then we lose the nice feature of being able to support * these messages in a real-time MIDI stream. * * Inputs: * pEASData - pointer to synthesizer instance data * c - character to be processed * locating - if true, the sequencer is relocating to a new position * * Outputs: * * * Side Effects: * * Notes: * These are the SysEx messages we can receive: * * SysEx messages * { f0 7e 7f 09 01 f7 } GM 1 On * { f0 7e 7f 09 02 f7 } GM 1/2 Off * { f0 7e 7f 09 03 f7 } GM 2 On * { f0 7f 7f 04 01 lsb msb } Master Volume * { f0 7f 7f 0b 01 ch mip [ch mip ...] f7 } SP-MIDI * { f0 00 01 3a 04 01 fdbk1 fdbk2 drive wet dry f7 } Enhancer * *---------------------------------------------------------------------------- */ static EAS_RESULT ProcessSysExMessage (S_EAS_DATA *pEASData, S_SYNTH *pSynth, S_MIDI_STREAM *pMIDIStream, EAS_U8 c, EAS_INT parserMode) { /* check for start byte */ if (c == 0xf0) { pMIDIStream->sysExState = eSysEx; } /* check for end byte */ else if (c == 0xf7) { /* if this was a MIP message, update the MIP table */ if ((pMIDIStream->sysExState == eSysExSPMIDIchan) && (parserMode != eParserModeMetaData)) VMUpdateMIPTable(pEASData->pVoiceMgr, pSynth); pMIDIStream->sysExState = eSysExIgnore; } /* process SysEx message */ else { switch (pMIDIStream->sysExState) { case eSysEx: /* first byte, determine message class */ switch (c) { case 0x7e: pMIDIStream->sysExState = eSysExUnivNonRealTime; break; case 0x7f: pMIDIStream->sysExState = eSysExUnivRealTime; break; case 0x00: pMIDIStream->sysExState = eSysExMfgID1; break; default: pMIDIStream->sysExState = eSysExIgnore; break; } break; /* process GM message */ case eSysExUnivNonRealTime: if (c == 0x7f) pMIDIStream->sysExState = eSysExUnivNrtTargetID; else pMIDIStream->sysExState = eSysExIgnore; break; case eSysExUnivNrtTargetID: if (c == 0x09) pMIDIStream->sysExState = eSysExGMControl; else pMIDIStream->sysExState = eSysExIgnore; break; case eSysExGMControl: if ((c == 1) || (c == 3)) { /* GM 1 or GM2 On, reset synth */ if (parserMode != eParserModeMetaData) { pMIDIStream->flags |= MIDI_FLAG_GM_ON; VMReset(pEASData->pVoiceMgr, pSynth, EAS_FALSE); VMInitMIPTable(pSynth); } pMIDIStream->sysExState = eSysExEOX; } else pMIDIStream->sysExState = eSysExIgnore; break; /* Process Master Volume and SP-MIDI */ case eSysExUnivRealTime: if (c == 0x7f) pMIDIStream->sysExState = eSysExUnivRtTargetID; else pMIDIStream->sysExState = eSysExIgnore; break; case eSysExUnivRtTargetID: if (c == 0x04) pMIDIStream->sysExState = eSysExDeviceControl; else if (c == 0x0b) pMIDIStream->sysExState = eSysExSPMIDI; else pMIDIStream->sysExState = eSysExIgnore; break; /* process master volume */ case eSysExDeviceControl: if (c == 0x01) pMIDIStream->sysExState = eSysExMasterVolume; else pMIDIStream->sysExState = eSysExIgnore; break; case eSysExMasterVolume: /* save LSB */ pMIDIStream->d1 = c; pMIDIStream->sysExState = eSysExMasterVolLSB; break; case eSysExMasterVolLSB: if (parserMode != eParserModeMetaData) { EAS_I32 gain = ((EAS_I32) c << 8) | ((EAS_I32) pMIDIStream->d1 << 1); gain = (gain * gain) >> 15; VMSetVolume(pSynth, (EAS_U16) gain); } pMIDIStream->sysExState = eSysExEOX; break; /* process SP-MIDI MIP message */ case eSysExSPMIDI: if (c == 0x01) { /* assume all channels are muted */ if (parserMode != eParserModeMetaData) VMInitMIPTable(pSynth); pMIDIStream->d1 = 0; pMIDIStream->sysExState = eSysExSPMIDIchan; } else pMIDIStream->sysExState = eSysExIgnore; break; case eSysExSPMIDIchan: if (c < NUM_SYNTH_CHANNELS) { pMIDIStream->d2 = c; pMIDIStream->sysExState = eSysExSPMIDIMIP; } else { /* bad MIP message - unmute channels */ if (parserMode != eParserModeMetaData) VMInitMIPTable(pSynth); pMIDIStream->sysExState = eSysExIgnore; } break; case eSysExSPMIDIMIP: /* process MIP entry here */ if (parserMode != eParserModeMetaData) VMSetMIPEntry(pEASData->pVoiceMgr, pSynth, pMIDIStream->d2, pMIDIStream->d1, c); pMIDIStream->sysExState = eSysExSPMIDIchan; /* if 16 channels received, update MIP table */ if (++pMIDIStream->d1 == NUM_SYNTH_CHANNELS) { if (parserMode != eParserModeMetaData) VMUpdateMIPTable(pEASData->pVoiceMgr, pSynth); pMIDIStream->sysExState = eSysExEOX; } break; /* process Enhancer */ case eSysExMfgID1: if (c == 0x01) pMIDIStream->sysExState = eSysExMfgID1; else pMIDIStream->sysExState = eSysExIgnore; break; case eSysExMfgID2: if (c == 0x3a) pMIDIStream->sysExState = eSysExMfgID1; else pMIDIStream->sysExState = eSysExIgnore; break; case eSysExMfgID3: if (c == 0x04) pMIDIStream->sysExState = eSysExEnhancer; else pMIDIStream->sysExState = eSysExIgnore; break; case eSysExEnhancer: if (c == 0x01) pMIDIStream->sysExState = eSysExEnhancerSubID; else pMIDIStream->sysExState = eSysExIgnore; break; case eSysExEnhancerSubID: pMIDIStream->sysExState = eSysExEnhancerFeedback1; break; case eSysExEnhancerFeedback1: pMIDIStream->sysExState = eSysExEnhancerFeedback2; break; case eSysExEnhancerFeedback2: pMIDIStream->sysExState = eSysExEnhancerDrive; break; case eSysExEnhancerDrive: pMIDIStream->sysExState = eSysExEnhancerWet; break; case eSysExEnhancerWet: pMIDIStream->sysExState = eSysExEOX; break; case eSysExEOX: { /* dpp: EAS_ReportEx(_EAS_SEVERITY_DETAIL, "Expected F7, received %02x\n", c); */ } pMIDIStream->sysExState = eSysExIgnore; break; case eSysExIgnore: break; default: pMIDIStream->sysExState = eSysExIgnore; break; } }