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