Example #1
0
void sysexHandler_Scumm(Player *player, const byte *msg, uint16 len) {
	Part *part;
	byte a;
	byte buf[128];

	IMuseInternal *se = player->_se;
	const byte *p = msg;

	byte code = 0;
	switch (code = *p++) {
	case 0:
		// Allocate new part.
		// There are 17 bytes of useful information here.
		// Here is what we know about them so far:
		//   BYTE 00: Channel #
		//   BYTE 02: BIT 01(0x01): Part on?(1 = yes)
		//            BIT 02(0x02): Reverb? (1 = yes) [bug #1088045]
		//   BYTE 04: Priority adjustment [guessing]
		//   BYTE 05: Volume(upper 4 bits) [guessing]
		//   BYTE 06: Volume(lower 4 bits) [guessing]
		//   BYTE 07: Pan(upper 4 bits) [bug #1088045]
		//   BYTE 08: Pan(lower 4 bits) [bug #1088045]
		//   BYTE 09: BIT 04(0x08): Percussion?(1 = yes)
		//   BYTE 13: Pitchbend range(upper 4 bits) [bug #1088045]
		//   BYTE 14: Pitchbend range(lower 4 bits) [bug #1088045]
		//   BYTE 15: Program(upper 4 bits)
		//   BYTE 16: Program(lower 4 bits)

		// athrxx (05-21-2011):
		// BYTE  9, 10: Transpose (if set to 0x80, this means that part->_transpose_eff will be 0 (also ignoring player->_transpose)
		// BYTE 11, 12: Detune

		part = player->getPart(p[0] & 0x0F);
		if (part) {
			part->set_onoff(p[2] & 0x01);
			part->effectLevel((p[2] & 0x02) ? 127 : 0);
			part->set_pri(p[4]);
			part->volume((p[5] & 0x0F) << 4 |(p[6] & 0x0F));
			part->set_pan((p[7] & 0x0F) << 4 | (p[8] & 0x0F));
			part->_percussion = player->_isMIDI ? ((p[9] & 0x08) > 0) : false;			
			part->set_transpose((p[9] & 0x0F) << 4 | (p[10] & 0x0F));
			part->set_detune((p[11] & 0x0F) << 4 | (p[12] & 0x0F));
			part->pitchBendFactor((p[13] & 0x0F) << 4 | (p[14] & 0x0F));
			if (part->_percussion) {
				if (part->_mc) {
					part->off();
					se->reallocateMidiChannels(player->_midi);
				}
			} else {
				// Even in cases where a program does not seem to be specified,
				// i.e. bytes 15 and 16 are 0, we send a program change because
				// 0 is a valid program number. MI2 tests show that in such
				// cases, a regular program change message always seems to follow
				// anyway.
				if (player->_isMIDI)
					part->_instrument.program((p[15] & 0x0F) << 4 |(p[16] & 0x0F), player->_isMT32);
				part->sendAll();
			}
		}
		break;

	case 1:
		// Shut down a part. [Bug 1088045, comments]
		part = player->getPart(p[0]);
		if (part != NULL)
			part->uninit();
		break;

	case 2: // Start of song. Ignore for now.
		break;

	case 16: // AdLib instrument definition(Part)
		a = *p++ & 0x0F;
		++p; // Skip hardware type
		part = player->getPart(a);
		if (part) {
			if (len == 62) {
				player->decode_sysex_bytes(p, buf, len - 2);
				part->set_instrument((byte *)buf);
			} else {
				// SPK tracks have len == 48 here, and are not supported
				part->programChange(254); // Must be invalid, but not 255 (which is reserved)
			}
		}
		break;

	case 17: // AdLib instrument definition(Global)
		p += 2; // Skip hardware type and... whatever came right before it
		a = *p++;
		player->decode_sysex_bytes(p, buf, len - 3);
		se->setGlobalAdLibInstrument(a, buf);
		break;

	case 33: // Parameter adjust
		a = *p++ & 0x0F;
		++p; // Skip hardware type
		player->decode_sysex_bytes(p, buf, len - 2);
		part = player->getPart(a);
		if (part)
			part->set_param(READ_BE_UINT16(buf), READ_BE_UINT16(buf + 2));
		break;

	case 48: // Hook - jump
		if (player->_scanning)
			break;
		player->decode_sysex_bytes(p + 1, buf, len - 1);
		player->maybe_jump(buf[0], READ_BE_UINT16(buf + 1), READ_BE_UINT16(buf + 3), READ_BE_UINT16(buf + 5));
		break;

	case 49: // Hook - global transpose
		player->decode_sysex_bytes(p + 1, buf, len - 1);
		player->maybe_set_transpose(buf);
		break;

	case 50: // Hook - part on/off
		buf[0] = *p++ & 0x0F;
		player->decode_sysex_bytes(p, buf + 1, len - 1);
		player->maybe_part_onoff(buf);
		break;

	case 51: // Hook - set volume
		buf[0] = *p++ & 0x0F;
		player->decode_sysex_bytes(p, buf + 1, len - 1);
		player->maybe_set_volume(buf);
		break;

	case 52: // Hook - set program
		buf[0] = *p++ & 0x0F;
		player->decode_sysex_bytes(p, buf + 1, len - 1);
		player->maybe_set_program(buf);
		break;

	case 53: // Hook - set transpose
		buf[0] = *p++ & 0x0F;
		player->decode_sysex_bytes(p, buf + 1, len - 1);
		player->maybe_set_transpose_part(buf);
		break;

	case 64: // Marker
		p++;
		len--;
		while (len--) {
			se->handle_marker(player->_id, *p++);
		}
		break;

	case 80: // Loop
		player->decode_sysex_bytes(p + 1, buf, len - 1);
		player->setLoop
			(READ_BE_UINT16(buf), READ_BE_UINT16(buf + 2),
			 READ_BE_UINT16(buf + 4), READ_BE_UINT16(buf + 6),
			 READ_BE_UINT16(buf + 8));
		break;

	case 81: // End loop
		player->clearLoop();
		break;

	case 96: // Set instrument
		part = player->getPart(p[0] & 0x0F);
		a = (p[1] & 0x0F) << 12 | (p[2] & 0x0F) << 8 | (p[3] & 0x0F) << 4 | (p[4] & 0x0F);
		if (part)
			part->set_instrument(a);
		break;

	default:
		error("Unknown SysEx command %d", (int)code);
	}
}
Example #2
0
void sysexHandler_Scumm(Player *player, const byte *msg, uint16 len) {
	Part *part;
	byte a;
	byte buf[128];

	IMuseInternal *se = player->_se;
	const byte *p = msg;

	byte code = 0;
	switch (code = *p++) {
	case 0:
		// Allocate new part.
		// There are 8 bytes (after decoding!) of useful information here.
		// Here is what we know about them so far:
		//   BYTE 0: Channel #
		//   BYTE 1: BIT 01(0x01): Part on?(1 = yes)
		//            BIT 02(0x02): Reverb? (1 = yes) [bug #1088045]
		//   BYTE 2: Priority adjustment
		//   BYTE 3: Volume [guessing]
		//   BYTE 4: Pan [bug #1088045]
		//   BYTE 5: BIT 8(0x80): Percussion?(1 = yes) [guessed?]
		//   BYTE 5: Transpose, if set to 0x80(=-1) it means no transpose
		//   BYTE 6: Detune
		//   BYTE 7: Pitchbend factor [bug #1088045]
		//   BYTE 8: Program

		part = player->getPart(p[0] & 0x0F);
		player->decode_sysex_bytes(p + 1, buf + 1, len - 1);
		if (part) {
			part->set_onoff(buf[1] & 0x01);
			part->effectLevel((buf[1] & 0x02) ? 127 : 0);
			part->set_pri(buf[2]);
			part->volume(buf[3]);
			part->set_pan(buf[4]);
			part->_percussion = player->_isMIDI ? ((buf[5] & 0x80) > 0) : false;
			part->set_transpose(buf[5]);
			part->set_detune(buf[6]);
			part->pitchBendFactor(buf[7]);
			if (part->_percussion) {
				if (part->_mc) {
					part->off();
					se->reallocateMidiChannels(player->_midi);
				}
			} else {
				if (player->_isMIDI) {
					// Even in cases where a program does not seem to be specified,
					// i.e. bytes 15 and 16 are 0, we send a program change because
					// 0 is a valid program number. MI2 tests show that in such
					// cases, a regular program change message always seems to follow
					// anyway.
					part->_instrument.program(buf[8], player->_isMT32);
				} else {
					// Like the original we set up the instrument data of the
					// specified program here too. In case the global
					// instrument data is not loaded already, this will take
					// care of setting a default instrument too.
					se->copyGlobalInstrument(buf[8], &part->_instrument);
				}
				part->sendAll();
			}
		}
		break;

	case 1:
		// Shut down a part. [Bug 1088045, comments]
		part = player->getPart(p[0]);
		if (part != NULL)
			part->uninit();
		break;

	case 2: // Start of song. Ignore for now.
		break;

	case 16: // AdLib instrument definition(Part)
		a = *p++ & 0x0F;
		++p; // Skip hardware type
		part = player->getPart(a);
		if (part) {
			if (len == 62 || len == 48) {
				player->decode_sysex_bytes(p, buf, len - 2);
				part->set_instrument((byte *)buf);
			} else {
				part->programChange(254); // Must be invalid, but not 255 (which is reserved)
			}
		}
		break;

	case 17: // AdLib instrument definition(Global)
		p += 2; // Skip hardware type and... whatever came right before it
		a = *p++;
		player->decode_sysex_bytes(p, buf, len - 3);
		if (len == 63 || len == 49)
			se->setGlobalInstrument(a, buf);
		break;

	case 33: // Parameter adjust
		a = *p++ & 0x0F;
		++p; // Skip hardware type
		player->decode_sysex_bytes(p, buf, len - 2);
		part = player->getPart(a);
		if (part)
			part->set_param(READ_BE_UINT16(buf), READ_BE_UINT16(buf + 2));
		break;

	case 48: // Hook - jump
		if (player->_scanning)
			break;
		player->decode_sysex_bytes(p + 1, buf, len - 1);
		player->maybe_jump(buf[0], READ_BE_UINT16(buf + 1), READ_BE_UINT16(buf + 3), READ_BE_UINT16(buf + 5));
		break;

	case 49: // Hook - global transpose
		player->decode_sysex_bytes(p + 1, buf, len - 1);
		player->maybe_set_transpose(buf);
		break;

	case 50: // Hook - part on/off
		buf[0] = *p++ & 0x0F;
		player->decode_sysex_bytes(p, buf + 1, len - 1);
		player->maybe_part_onoff(buf);
		break;

	case 51: // Hook - set volume
		buf[0] = *p++ & 0x0F;
		player->decode_sysex_bytes(p, buf + 1, len - 1);
		player->maybe_set_volume(buf);
		break;

	case 52: // Hook - set program
		buf[0] = *p++ & 0x0F;
		player->decode_sysex_bytes(p, buf + 1, len - 1);
		player->maybe_set_program(buf);
		break;

	case 53: // Hook - set transpose
		buf[0] = *p++ & 0x0F;
		player->decode_sysex_bytes(p, buf + 1, len - 1);
		player->maybe_set_transpose_part(buf);
		break;

	case 64: // Marker
		p++;
		len--;
		while (len--) {
			se->handle_marker(player->_id, *p++);
		}
		break;

	case 80: // Loop
		player->decode_sysex_bytes(p + 1, buf, len - 1);
		player->setLoop(READ_BE_UINT16(buf), READ_BE_UINT16(buf + 2),
		                READ_BE_UINT16(buf + 4), READ_BE_UINT16(buf + 6),
		                READ_BE_UINT16(buf + 8));
		break;

	case 81: // End loop
		player->clearLoop();
		break;

	case 96: // Set instrument
		part = player->getPart(p[0] & 0x0F);
		a = (p[1] & 0x0F) << 12 | (p[2] & 0x0F) << 8 | (p[3] & 0x0F) << 4 | (p[4] & 0x0F);
		if (part)
			part->set_instrument(a);
		break;

	default:
		error("Unknown SysEx command %d", (int)code);
	}
}