|
|
1.1 root 1: /*
1.1.1.2 root 2: Hatari - midi.c
1.1 root 3:
1.1.1.2 root 4: This file is distributed under the GNU Public License, version 2 or at
5: your option any later version. Read the file gpl.txt for details.
6:
7: MIDI communication.
8: Note that this code is far from being perfect. However, it is already
9: enough to let some ST programs (e.g. the game Pirates!) use the host's midi
10: system.
11:
12: TODO:
13: - Midi input (??)
14: - No exact timing yet: Sending MIDI data should probably rather be done
15: with an "interrupt" from int.c (just like it is done by the code in
16: ikbd.c).
17: - Most bits in the ACIA's status + control registers are currently ignored.
18: - Check when we have to clear the ACIA_SR_INTERRUPT_REQUEST bit in the
19: ACIA status register (it is currently done when reading or writing to
20: the data register, but probably it should rather be done when reading the
21: status register?).
1.1 root 22: */
1.1.1.5 ! root 23: const char Midi_rcsid[] = "Hatari $Id: midi.c,v 1.9 2007/02/25 21:20:10 eerot Exp $";
1.1.1.2 root 24:
25: #include <SDL_types.h>
1.1 root 26:
27: #include "main.h"
1.1.1.2 root 28: #include "configuration.h"
1.1.1.3 root 29: #include "ioMem.h"
1.1.1.4 root 30: #include "m68000.h"
1.1.1.2 root 31: #include "mfp.h"
32: #include "midi.h"
1.1.1.5 ! root 33: #include "file.h"
1.1.1.2 root 34:
35:
36: #define ACIA_SR_INTERRUPT_REQUEST 0x80
37:
38: #define MIDI_DEBUG 0
39: #if MIDI_DEBUG
40: #define Dprintf(a) printf a
41: #else
42: #define Dprintf(a)
43: #endif
44:
45:
46: static FILE *pMidiOutFileHandle = NULL; /* Used for Midi output */
47: static Uint8 MidiControlRegister;
48: static Uint8 MidiStatusRegister;
49:
50:
51: /*-----------------------------------------------------------------------*/
1.1.1.5 ! root 52: /**
! 53: * Initialization: Open MIDI device.
! 54: */
1.1.1.2 root 55: void Midi_Init(void)
56: {
57: MidiStatusRegister = 2;
58:
1.1.1.5 ! root 59: if (!ConfigureParams.Midi.bEnableMidi)
! 60: return;
1.1.1.2 root 61:
1.1.1.5 ! root 62: /* Open MIDI file... */
! 63: pMidiOutFileHandle = File_Open(ConfigureParams.Midi.szMidiOutFileName, "wb");
! 64: if (!pMidiOutFileHandle)
! 65: {
! 66: ConfigureParams.Midi.bEnableMidi = FALSE;
! 67: return;
1.1.1.2 root 68: }
1.1.1.5 ! root 69: Dprintf(("Opened midi file '%s'.\n", ConfigureParams.Midi.szMidiOutFileName));
1.1.1.2 root 70: }
71:
72:
73: /*-----------------------------------------------------------------------*/
1.1.1.5 ! root 74: /**
! 75: * Close MIDI device.
! 76: */
1.1.1.2 root 77: void Midi_UnInit(void)
78: {
1.1.1.5 ! root 79: pMidiOutFileHandle = File_Close(pMidiOutFileHandle);
1.1.1.2 root 80: }
81:
82:
83: /*-----------------------------------------------------------------------*/
1.1.1.5 ! root 84: /**
! 85: * Read MIDI status register ($FFFC04).
! 86: */
1.1.1.3 root 87: void Midi_Control_ReadByte(void)
1.1.1.2 root 88: {
89: /* Dprintf(("Midi_ReadControl : $%x.\n", MidiStatusRegister)); */
90:
1.1.1.4 root 91: /* ACIA registers need wait states - but the value seems to vary in certain cases */
92: M68000_WaitState(8);
93:
1.1.1.3 root 94: IoMem[0xfffc04] = MidiStatusRegister;
1.1.1.2 root 95: }
96:
97:
98: /*-----------------------------------------------------------------------*/
1.1.1.5 ! root 99: /**
! 100: * Read MIDI data register ($FFFC06).
! 101: */
1.1.1.3 root 102: void Midi_Data_ReadByte(void)
1.1.1.2 root 103: {
104: Dprintf(("Midi_ReadData : $%x.\n", 1));
105:
1.1.1.4 root 106: /* ACIA registers need wait states - but the value seems to vary in certain cases */
107: M68000_WaitState(8);
108:
1.1.1.2 root 109: MidiStatusRegister &= ~ACIA_SR_INTERRUPT_REQUEST;
110:
1.1.1.3 root 111: IoMem[0xfffc06] = 1; /* Should be this? */
1.1.1.2 root 112: }
113:
1.1 root 114:
115: /*-----------------------------------------------------------------------*/
1.1.1.5 ! root 116: /**
! 117: * Write to MIDI control register ($FFFC04).
! 118: */
1.1.1.3 root 119: void Midi_Control_WriteByte(void)
1.1.1.2 root 120: {
1.1.1.4 root 121: /* ACIA registers need wait states - but the value seems to vary in certain cases */
122: M68000_WaitState(8);
123:
1.1.1.3 root 124: MidiControlRegister = IoMem[0xfffc04];
1.1.1.2 root 125:
1.1.1.3 root 126: Dprintf(("Midi_WriteControl($%x)\n", MidiControlRegister));
1.1.1.2 root 127:
128: /* Do we need to generate a transfer interrupt? */
129: if ((MidiControlRegister & 0xA0) == 0xA0)
130: {
131: Dprintf(("WriteControl: Transfer interrupt!\n"));
132:
133: /* Acknowledge in MFP circuit, pass bit,enable,pending */
134: MFP_InputOnChannel(MFP_ACIA_BIT, MFP_IERB, &MFP_IPRB);
135:
136: MidiStatusRegister |= ACIA_SR_INTERRUPT_REQUEST;
137: }
138: }
139:
140:
141: /*-----------------------------------------------------------------------*/
1.1.1.5 ! root 142: /**
! 143: * Write to MIDI data register ($FFFC06).
! 144: */
1.1.1.3 root 145: void Midi_Data_WriteByte(void)
1.1.1.2 root 146: {
1.1.1.4 root 147: Uint8 dataByte;
148:
149: /* ACIA registers need wait states - but the value seems to vary in certain cases */
150: M68000_WaitState(8);
151:
152: dataByte = IoMem[0xfffc06];
1.1.1.3 root 153:
1.1.1.2 root 154: Dprintf(("Midi_WriteData($%x)\n", dataByte));
155:
156: MidiStatusRegister &= ~ACIA_SR_INTERRUPT_REQUEST;
157:
158: if (!ConfigureParams.Midi.bEnableMidi)
159: return;
160:
161: if (pMidiOutFileHandle)
162: {
163: int ret;
164:
165: /* Write the character to the output file: */
166: ret = fputc(dataByte, pMidiOutFileHandle);
167:
168: /* If there was an error then stop the midi emulation */
169: if (ret == EOF)
170: {
171: Midi_UnInit();
172: return;
173: }
174:
175: /* Do not queue the midi data! */
176: fflush(pMidiOutFileHandle);
177: }
178:
179: /* Do we need to generate a transfer interrupt? */
180: if ((MidiControlRegister & 0xA0) == 0xA0)
181: {
182: Dprintf(("WriteData: Transfer interrupt!\n"));
183:
184: /* Acknowledge in MFP circuit, pass bit,enable,pending */
185: MFP_InputOnChannel(MFP_ACIA_BIT, MFP_IERB, &MFP_IPRB);
186:
187: MidiStatusRegister |= ACIA_SR_INTERRUPT_REQUEST;
188: }
189: }
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.