|
|
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.3 ! root 23: char Midi_rcsid[] = "Hatari $Id: midi.c,v 1.5 2005/01/18 23:33:24 thothy 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.2 root 30: #include "mfp.h"
31: #include "midi.h"
32:
33:
34: #define ACIA_SR_INTERRUPT_REQUEST 0x80
35:
36:
37: #define MIDI_DEBUG 0
38:
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: /*-----------------------------------------------------------------------*/
52: /*
53: Initialization: Open MIDI device.
54: */
55: void Midi_Init(void)
56: {
57: MidiStatusRegister = 2;
58:
59: if (ConfigureParams.Midi.bEnableMidi)
60: {
61: /* Open MIDI file... */
62: pMidiOutFileHandle = fopen(ConfigureParams.Midi.szMidiOutFileName, "wb");
63:
64: if (!pMidiOutFileHandle)
65: {
66: fprintf(stderr, "Failed to open %s.\n", ConfigureParams.Midi.szMidiOutFileName);
67: ConfigureParams.Midi.bEnableMidi = FALSE;
68: return;
69: }
70:
71: Dprintf(("Opened midi file %s.\n", ConfigureParams.Midi.szMidiOutFileName));
72: }
73: }
74:
75:
76: /*-----------------------------------------------------------------------*/
77: /*
78: Close MIDI device.
79: */
80: void Midi_UnInit(void)
81: {
82: if (pMidiOutFileHandle)
83: {
84: /* Close MIDI file... */
85: fclose(pMidiOutFileHandle);
86: pMidiOutFileHandle = NULL;
87: }
88: }
89:
90:
91: /*-----------------------------------------------------------------------*/
92: /*
93: Read MIDI status register ($FFFC04).
94: */
1.1.1.3 ! root 95: void Midi_Control_ReadByte(void)
1.1.1.2 root 96: {
97: /* Dprintf(("Midi_ReadControl : $%x.\n", MidiStatusRegister)); */
98:
1.1.1.3 ! root 99: IoMem[0xfffc04] = MidiStatusRegister;
1.1.1.2 root 100: }
101:
102:
103: /*-----------------------------------------------------------------------*/
104: /*
105: Read MIDI data register ($FFFC06).
106: */
1.1.1.3 ! root 107: void Midi_Data_ReadByte(void)
1.1.1.2 root 108: {
109: Dprintf(("Midi_ReadData : $%x.\n", 1));
110:
111: MidiStatusRegister &= ~ACIA_SR_INTERRUPT_REQUEST;
112:
1.1.1.3 ! root 113: IoMem[0xfffc06] = 1; /* Should be this? */
1.1.1.2 root 114: }
115:
1.1 root 116:
117: /*-----------------------------------------------------------------------*/
118: /*
1.1.1.2 root 119: Write to MIDI control register ($FFFC04).
1.1 root 120: */
1.1.1.3 ! root 121: void Midi_Control_WriteByte(void)
1.1.1.2 root 122: {
1.1.1.3 ! root 123: MidiControlRegister = IoMem[0xfffc04];
1.1.1.2 root 124:
1.1.1.3 ! root 125: Dprintf(("Midi_WriteControl($%x)\n", MidiControlRegister));
1.1.1.2 root 126:
127: /* Do we need to generate a transfer interrupt? */
128: if ((MidiControlRegister & 0xA0) == 0xA0)
129: {
130: Dprintf(("WriteControl: Transfer interrupt!\n"));
131:
132: /* Acknowledge in MFP circuit, pass bit,enable,pending */
133: MFP_InputOnChannel(MFP_ACIA_BIT, MFP_IERB, &MFP_IPRB);
134:
135: MidiStatusRegister |= ACIA_SR_INTERRUPT_REQUEST;
136: }
137: }
138:
139:
140: /*-----------------------------------------------------------------------*/
141: /*
142: Write to MIDI data register ($FFFC06).
143: */
1.1.1.3 ! root 144: void Midi_Data_WriteByte(void)
1.1.1.2 root 145: {
1.1.1.3 ! root 146: Uint8 dataByte = IoMem[0xfffc06];
! 147:
1.1.1.2 root 148: Dprintf(("Midi_WriteData($%x)\n", dataByte));
149:
150: MidiStatusRegister &= ~ACIA_SR_INTERRUPT_REQUEST;
151:
152: if (!ConfigureParams.Midi.bEnableMidi)
153: return;
154:
155: if (pMidiOutFileHandle)
156: {
157: int ret;
158:
159: /* Write the character to the output file: */
160: ret = fputc(dataByte, pMidiOutFileHandle);
161:
162: /* If there was an error then stop the midi emulation */
163: if (ret == EOF)
164: {
165: Midi_UnInit();
166: return;
167: }
168:
169: /* Do not queue the midi data! */
170: fflush(pMidiOutFileHandle);
171: }
172:
173: /* Do we need to generate a transfer interrupt? */
174: if ((MidiControlRegister & 0xA0) == 0xA0)
175: {
176: Dprintf(("WriteData: Transfer interrupt!\n"));
177:
178: /* Acknowledge in MFP circuit, pass bit,enable,pending */
179: MFP_InputOnChannel(MFP_ACIA_BIT, MFP_IERB, &MFP_IPRB);
180:
181: MidiStatusRegister |= ACIA_SR_INTERRUPT_REQUEST;
182: }
183: }
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.