2D Run-and-gun shooter inspired by One Man's Doomsday, Counter-Strike, and Metal Slug.
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
 
 
 
 
 
 

163 lines
4.6 KiB

  1. #include "IZ_midi.h"
  2. void IZ_MIDIInputHandleNoteOnOffEvents(IZ_MIDIInputState* state, IZ_Action* action, PmEvent e) {
  3. u32 message = e.message;
  4. u8 status = message & 0xF0u;
  5. u8 channel = message & 0x0Fu;
  6. u8 data1 = (message >> 8) & 0xFFu;
  7. // u8 data2 = (message >> 16) & 0xFFu;
  8. u8 control_index;
  9. for (control_index = 0; control_index < CONTROLS; control_index += 1) {
  10. if (
  11. data1 == state->config.control_mapping[control_index]
  12. && (
  13. (state->config.channel < 16 && channel == state->config.channel)
  14. || state->config.channel >= 16
  15. )
  16. ) {
  17. const u16 bitflag = (0x1 << control_index);
  18. if (status == IZ_MIDI_NOTE_ON) {
  19. *action |= bitflag;
  20. return;
  21. }
  22. if (status == IZ_MIDI_NOTE_OFF) {
  23. *action &= ~bitflag;
  24. return;
  25. }
  26. }
  27. }
  28. }
  29. void IZ_MIDIInputHandleEvents(IZ_MIDIInputState(* state)[IZ_PLAYERS], IZ_Action(* action)[IZ_PLAYERS], PmEvent e) {
  30. u8 player_index;
  31. for (player_index = 0; player_index < IZ_PLAYERS; player_index += 1) {
  32. IZ_MIDIInputHandleNoteOnOffEvents(&(*state)[player_index], &(*action)[player_index], e);
  33. }
  34. }
  35. IZ_ProcedureResult IZ_MIDIInputSaveConfig(IZ_MIDIInputState(* state)[IZ_PLAYERS], const char* config_path) {
  36. u8 problem = 0;
  37. char control_mapping_section_name[27];
  38. char main_section_name[12];
  39. u8 player_index;
  40. u8 control_index;
  41. for (player_index = 0; player_index < IZ_PLAYERS; player_index += 1) {
  42. sprintf_s(control_mapping_section_name, 27, "MIDIInput.%d.ControlMapping", player_index);
  43. for (control_index = 0; control_index < CONTROLS; control_index += 1) {
  44. if (!ini_puts(
  45. control_mapping_section_name,
  46. ACTION_NAMES[control_index],
  47. IZ_MIDIGetNoteName((*state)[player_index].config.control_mapping[control_index]),
  48. config_path
  49. )) {
  50. problem |= (1 << player_index);
  51. }
  52. }
  53. sprintf_s(main_section_name, 12, "MIDIInput.%d", player_index);
  54. if (!ini_putl(
  55. main_section_name,
  56. "Channel",
  57. (*state)[player_index].config.channel,
  58. config_path
  59. )) {
  60. problem |= (1 << player_index);
  61. }
  62. if (!ini_putl(
  63. main_section_name,
  64. "DeviceID",
  65. (*state)[player_index].config.device_id,
  66. config_path
  67. )) {
  68. problem |= (1 << player_index);
  69. }
  70. }
  71. return problem;
  72. }
  73. void IZ_MIDIInputLoadConfig(IZ_MIDIInputState(* state)[IZ_PLAYERS], const char* config_path) {
  74. char buffer[128];
  75. char control_mapping_section_name[27];
  76. char main_section_name[12];
  77. u8 player_index;
  78. u8 control_index;
  79. for (player_index = 0; player_index < IZ_PLAYERS; player_index += 1) {
  80. sprintf_s(control_mapping_section_name, 27, "MIDIInput.%d.ControlMapping", player_index);
  81. for (control_index = 0; control_index < CONTROLS; control_index += 1) {
  82. ini_gets(
  83. control_mapping_section_name,
  84. ACTION_NAMES[control_index],
  85. IZ_MIDIGetNoteName(IZ_MIDI_INPUT_DEFAULT_STATE[player_index].config.control_mapping[control_index]),
  86. buffer,
  87. 128,
  88. config_path
  89. );
  90. (*state)[player_index].config.control_mapping[control_index] = IZ_MIDIGetNoteFromName(buffer);
  91. }
  92. sprintf_s(main_section_name, 12, "MIDIInput.%d", player_index);
  93. (*state)[player_index].config.channel = ini_getl(main_section_name, "Channel", player_index, config_path);
  94. (*state)[player_index].config.device_id = ini_getl(main_section_name, "DeviceID", player_index, config_path);
  95. }
  96. }
  97. IZ_ProcedureResult IZ_MIDIInputInitialize(IZ_MIDIInputState(* state)[IZ_PLAYERS], const char* config_path, u8 argc, const char* argv[]) {
  98. if (Pm_Initialize()) {
  99. return 1;
  100. }
  101. SDL_memcpy(state, &IZ_MIDI_INPUT_DEFAULT_STATE, sizeof(IZ_MIDIInputState));
  102. IZ_MIDIInputLoadConfig(state, config_path);
  103. if (IZ_MIDIInputSaveConfig(state, config_path)) {
  104. return 2;
  105. }
  106. u8 player_index;
  107. u8 midi_devices_count = Pm_CountDevices();
  108. u8 input_midi_devices_count = 0;
  109. u8 device_index;
  110. for (device_index = 0; device_index < midi_devices_count; device_index += 1) {
  111. if (!Pm_GetDeviceInfo(device_index)->output) {
  112. continue;
  113. }
  114. // midi device can output messages for the app to receive
  115. input_midi_devices_count += 1;
  116. }
  117. for (player_index = 0; player_index < input_midi_devices_count; player_index += 1) {
  118. if (player_index >= IZ_PLAYERS) {
  119. break;
  120. }
  121. (*state)[player_index].device_info = Pm_GetDeviceInfo((*state)[player_index].config.device_id);
  122. (*state)[player_index].stream = NULL;
  123. Pm_OpenInput(
  124. &(*state)[player_index].stream,
  125. (*state)[player_index].config.device_id,
  126. NULL,
  127. MIDI_EVENT_BUFFER_SIZE,
  128. NULL,
  129. NULL
  130. );
  131. }
  132. return 0;
  133. }
  134. void IZ_MIDIInputTeardown(IZ_MIDIInputState(* state)[IZ_PLAYERS]) {
  135. u8 player_index;
  136. for (player_index = 0; player_index < IZ_PLAYERS; player_index += 1) {
  137. if (!(*state)[player_index].stream) {
  138. continue;
  139. }
  140. Pm_Close((*state)[player_index].stream);
  141. }
  142. }