From ac307615543ecb050ff73a1114b49cc64208c076 Mon Sep 17 00:00:00 2001 From: Tim Stirrat Date: Tue, 3 Sep 2024 10:35:04 +1000 Subject: [PATCH] Allow SysEx to pass through to mGB Allows SysEx messages of type 0x70 to pass through to mGB --- Arduinoboy/Mode_MidiGb.ino | 72 +++++++++++++++++++++++++++++++++++++- 1 file changed, 71 insertions(+), 1 deletion(-) diff --git a/Arduinoboy/Mode_MidiGb.ino b/Arduinoboy/Mode_MidiGb.ino index 5df6a7b..e691445 100644 --- a/Arduinoboy/Mode_MidiGb.ino +++ b/Arduinoboy/Mode_MidiGb.ino @@ -36,7 +36,7 @@ void modeMidiGb() if(!checkForProgrammerSysex(incomingMidiByte) && !usbMode) serial->write(incomingMidiByte); //Echo the Byte to MIDI Output - if(incomingMidiByte & 0x80) { + if(incomingMidiByte & 0xF0) { switch (incomingMidiByte & 0xF0) { case 0xF0: midiValueMode = false; @@ -119,6 +119,9 @@ void sendByteToGameboy(byte send_byte) } } +// Are we capturing SysEx bytes? +bool isSysexMessage = false; + void modeMidiGbUsbMidiReceive() { #ifdef USE_TEENSY @@ -195,6 +198,13 @@ void modeMidiGbUsbMidiReceive() do { rx = MidiUSB.read(); + + maybePassThroughSysex(rx.byte1); + maybePassThroughSysex(rx.byte2); + maybePassThroughSysex(rx.byte3); + + if (isSysexMessage) continue; + uint8_t ch = rx.byte1 & 0x0F; boolean send = false; if(ch == memory[MEM_MGB_CH]) { @@ -264,3 +274,63 @@ void modeMidiGbUsbMidiReceive() } while (rx.header != 0); #endif } + +#define MIDI_SYSEX_BYTE 0xF0 +#define MIDI_SYSEX_EOF 0xF7 + +#define SYSEX_ID_NON_COMMERCIAL 0x7D + +// What MFG id did we find, if we find the mGB one, we'll pass through all the bits +byte capturedSysexId = 0x00; + +// Passes through sysex messages to the GB if they are of the form: +// `0xF0 0x7D ..... 0xF7` +void maybePassThroughSysex(byte incomingMidiByte) { + // byte 1 - Check for SysEx status byte + if (!isSysexMessage && incomingMidiByte == MIDI_SYSEX_BYTE) { + isSysexMessage = true; + capturedSysexId = 0x00; // prompt check for mfg_id + blinkLight(0x90+2, 1); + return; + } + + if (!isSysexMessage) return; + + // byte 2 (mfg_id) + if (capturedSysexId == 0x00) { + capturedSysexId = incomingMidiByte; + + // only if it's the right id + if (capturedSysexId == SYSEX_ID_NON_COMMERCIAL) { + // replay Sysex status byte, since we skipped it + sendByteToGameboy(MIDI_SYSEX_BYTE); + delayMicroseconds(GB_MIDI_DELAY); + blinkLight(0x90+2, 1); + + // forward current byte (mfg id) + sendByteToGameboy(capturedSysexId); + delayMicroseconds(GB_MIDI_DELAY); + blinkLight(0x90+2, 1); + } + return; + } + + // stop passthrough, wrong id + if (capturedSysexId != SYSEX_ID_NON_COMMERCIAL) { + isSysexMessage = false; + capturedSysexId = 0x00; + return; + } + + // stop passing through, EOF + if (incomingMidiByte == MIDI_SYSEX_EOF) { + isSysexMessage = false; + capturedSysexId = 0x00; + } + + // send bytes (incl EOF) + sendByteToGameboy(incomingMidiByte); + delayMicroseconds(GB_MIDI_DELAY); + blinkLight(0x90+2, 1); + +}