PCem
changeset 3:ee7a3f8ad75d
Added preliminary MPU-401 emulation (UART mode only) for SB16. Currently outputs to default Windows MIDI device. This allows Windows 3.x SB16 drivers to work.
| author | TomW |
|---|---|
| date | Tue Jun 04 20:52:17 2013 +0100 |
| parents | 9c201151bb4b |
| children | 342c3f6cee85 |
| files | src/Makefile.mingw src/plat-midi.h src/sound_mpu401_uart.c src/sound_mpu401_uart.h src/sound_sb.c src/win-midi.c src/win.c |
| diffstat | 7 files changed, 152 insertions(+), 15 deletions(-) [+] |
line diff
1.1 --- a/src/Makefile.mingw Mon May 27 19:56:33 2013 +0100 1.2 +++ b/src/Makefile.mingw Tue Jun 04 20:52:17 2013 +0100 1.3 @@ -9,17 +9,17 @@ 1.4 keyboard_olim24.o keyboard_xt.o lpt.o mcr.o mem.o model.o \ 1.5 mouse.o mouse_ps2.o mouse_serial.o neat.o nvr.o olivetti_m24.o \ 1.6 opti.o pc.o pci.o pic.o piix.o pit.o ppi.o serial.o sound.o sound_adlib.o \ 1.7 - sound_adlibgold.o sound_cms.o sound_gus.o sound_opl.o sound_pas16.o sound_sb.o \ 1.8 - sound_sb_dsp.o sound_sn76489.o sound_speaker.o sound_wss.o soundopenal.o timer.o \ 1.9 - um8881f.o um8669f.o vid_ati_eeprom.o vid_ati_mach64.o vid_ati18800.o \ 1.10 - vid_ati28800.o vid_ati68860_ramdac.o vid_cga.o vid_cl5429.o vid_ega.o \ 1.11 - vid_et4000.o vid_et4000w32.o vid_et4000w32i.o vid_hercules.o vid_icd2061.o \ 1.12 - vid_ics2595.o vid_mda.o vid_olivetti_m24.o vid_oti067.o vid_paradise.o \ 1.13 - vid_pc1512.o vid_pc1640.o vid_pc200.o vid_s3.o vid_s3_virge.o vid_sdac_ramdac.o \ 1.14 - vid_stg_ramdac.o vid_svga.o vid_svga_render.o vid_tandy.o vid_tkd8001_ramdac.o \ 1.15 - vid_tvga.o vid_unk_ramdac.o vid_vga.o vid_voodoo.o video.o wd76c10.o \ 1.16 - win.o win-ddraw.o win-keyboard.o win-mouse.o win-timer.o win-video.o \ 1.17 - x86seg.o x87.o xtide.o pc.res 1.18 + sound_adlibgold.o sound_cms.o sound_gus.o sound_mpu401_uart.o sound_opl.o \ 1.19 + sound_pas16.o sound_sb.o sound_sb_dsp.o sound_sn76489.o sound_speaker.o \ 1.20 + sound_wss.o soundopenal.o timer.o um8881f.o um8669f.o vid_ati_eeprom.o \ 1.21 + vid_ati_mach64.o vid_ati18800.o vid_ati28800.o vid_ati68860_ramdac.o vid_cga.o \ 1.22 + vid_cl5429.o vid_ega.o vid_et4000.o vid_et4000w32.o vid_et4000w32i.o \ 1.23 + vid_hercules.o vid_icd2061.o vid_ics2595.o vid_mda.o vid_olivetti_m24.o \ 1.24 + vid_oti067.o vid_paradise.o vid_pc1512.o vid_pc1640.o vid_pc200.o vid_s3.o \ 1.25 + vid_s3_virge.o vid_sdac_ramdac.o vid_stg_ramdac.o vid_svga.o vid_svga_render.o \ 1.26 + vid_tandy.o vid_tkd8001_ramdac.o vid_tvga.o vid_unk_ramdac.o vid_vga.o \ 1.27 + vid_voodoo.o video.o wd76c10.o win.o win-ddraw.o win-keyboard.o win-midi.o \ 1.28 + win-mouse.o win-timer.o win-video.o x86seg.o x87.o xtide.o pc.res 1.29 FMOBJ = fmopl.o ymf262.o 1.30 1.31
2.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000 2.2 +++ b/src/plat-midi.h Tue Jun 04 20:52:17 2013 +0100 2.3 @@ -0,0 +1,3 @@ 2.4 +void midi_init(); 2.5 +void midi_close(); 2.6 +void midi_out(uint8_t val);
3.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000 3.2 +++ b/src/sound_mpu401_uart.c Tue Jun 04 20:52:17 2013 +0100 3.3 @@ -0,0 +1,57 @@ 3.4 +#include "ibm.h" 3.5 +#include "io.h" 3.6 +#include "sound_mpu401_uart.h" 3.7 + 3.8 +enum 3.9 +{ 3.10 + STATUS_OUTPUT_NOT_READY = 0x40, 3.11 + STATUS_INPUT_NOT_READY = 0x80 3.12 +}; 3.13 + 3.14 +static void mpu401_uart_write(uint16_t addr, uint8_t val, void *p) 3.15 +{ 3.16 + mpu401_uart_t *mpu = (mpu401_uart_t *)p; 3.17 + 3.18 + if (addr & 1) /*Command*/ 3.19 + { 3.20 + switch (val) 3.21 + { 3.22 + case 0xff: /*Reset*/ 3.23 + mpu->rx_data = 0xfe; /*Acknowledge*/ 3.24 + mpu->status = 0; 3.25 + mpu->uart_mode = 0; 3.26 + break; 3.27 + 3.28 + case 0x3f: /*Enter UART mode*/ 3.29 + mpu->rx_data = 0xfe; /*Acknowledge*/ 3.30 + mpu->status = 0; 3.31 + mpu->uart_mode = 1; 3.32 + break; 3.33 + } 3.34 + return; 3.35 + } 3.36 + 3.37 + /*Data*/ 3.38 + if (mpu->uart_mode) 3.39 + midi_out(val); 3.40 +} 3.41 + 3.42 +static uint8_t mpu401_uart_read(uint16_t addr, void *p) 3.43 +{ 3.44 + mpu401_uart_t *mpu = (mpu401_uart_t *)p; 3.45 + 3.46 + if (addr & 1) /*Status*/ 3.47 + return mpu->status; 3.48 + 3.49 + /*Data*/ 3.50 + mpu->status |= STATUS_INPUT_NOT_READY; 3.51 + return mpu->rx_data; 3.52 +} 3.53 + 3.54 +void mpu401_uart_init(mpu401_uart_t *mpu, uint16_t addr) 3.55 +{ 3.56 + mpu->status = STATUS_INPUT_NOT_READY; 3.57 + mpu->uart_mode = 0; 3.58 + 3.59 + io_sethandler(addr, 0x0002, mpu401_uart_read, NULL, NULL, mpu401_uart_write, NULL, NULL, mpu); 3.60 +}
4.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000 4.2 +++ b/src/sound_mpu401_uart.h Tue Jun 04 20:52:17 2013 +0100 4.3 @@ -0,0 +1,9 @@ 4.4 +typedef struct mpu401_uart_t 4.5 +{ 4.6 + uint8_t status; 4.7 + uint8_t rx_data; 4.8 + 4.9 + int uart_mode; 4.10 +} mpu401_uart_t; 4.11 + 4.12 +void mpu401_uart_init(mpu401_uart_t *mpu, uint16_t addr);
5.1 --- a/src/sound_sb.c Mon May 27 19:56:33 2013 +0100 5.2 +++ b/src/sound_sb.c Tue Jun 04 20:52:17 2013 +0100 5.3 @@ -1,9 +1,10 @@ 5.4 #include <stdlib.h> 5.5 #include "ibm.h" 5.6 #include "device.h" 5.7 +#include "sound_mpu401_uart.h" 5.8 +#include "sound_opl.h" 5.9 #include "sound_sb.h" 5.10 #include "sound_sb_dsp.h" 5.11 -#include "sound_opl.h" 5.12 5.13 #include "filters.h" 5.14 5.15 @@ -22,9 +23,10 @@ 5.16 5.17 typedef struct sb_t 5.18 { 5.19 - opl_t opl; 5.20 - sb_dsp_t dsp; 5.21 - sb_mixer_t mixer; 5.22 + opl_t opl; 5.23 + sb_dsp_t dsp; 5.24 + sb_mixer_t mixer; 5.25 + mpu401_uart_t mpu; 5.26 5.27 int16_t opl_buffer[SOUNDBUFLEN * 2]; 5.28 int16_t dsp_buffer[SOUNDBUFLEN * 2]; 5.29 @@ -336,6 +338,7 @@ 5.30 io_sethandler(0x0388, 0x0002, opl3_read, NULL, NULL, opl3_write, NULL, NULL, &sb->opl); 5.31 io_sethandler(0x0224, 0x0002, sb_16_mixer_read, NULL, NULL, sb_16_mixer_write, NULL, NULL, sb); 5.32 sound_add_handler(sb_opl3_poll, sb_get_buffer, sb); 5.33 + mpu401_uart_init(&sb->mpu, 0x330); 5.34 5.35 sb->mixer.regs[0x30] = 31 << 3; 5.36 sb->mixer.regs[0x31] = 31 << 3;
6.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000 6.2 +++ b/src/win-midi.c Tue Jun 04 20:52:17 2013 +0100 6.3 @@ -0,0 +1,62 @@ 6.4 +#include <windows.h> 6.5 +#include <mmsystem.h> 6.6 +#include "ibm.h" 6.7 +#include "plat-midi.h" 6.8 + 6.9 +static int midi_id; 6.10 +static HMIDIOUT midi_out_device = NULL; 6.11 + 6.12 +void midi_close(); 6.13 + 6.14 +void midi_init() 6.15 +{ 6.16 + int c; 6.17 + int n; 6.18 + MIDIOUTCAPS ocaps; 6.19 + MMRESULT hr; 6.20 + 6.21 + midi_id=0; 6.22 + 6.23 + hr = midiOutOpen(&midi_out_device, midi_id, 0, 6.24 + 0, CALLBACK_NULL); 6.25 + if (hr != MMSYSERR_NOERROR) { 6.26 + printf("midiOutOpen error - %08X\n",hr); 6.27 + return; 6.28 + } 6.29 + 6.30 + midiOutReset(midi_out_device); 6.31 +} 6.32 + 6.33 +void midi_close() 6.34 +{ 6.35 + if (midi_out_device != NULL) 6.36 + { 6.37 + midiOutReset(midi_out_device); 6.38 + midiOutClose(midi_out_device); 6.39 + midi_out_device = NULL; 6.40 + } 6.41 +} 6.42 + 6.43 +static int midi_pos, midi_len; 6.44 +static uint32_t midi_command; 6.45 +static int midi_lengths[8] = {3, 3, 3, 3, 2, 2, 3, 0}; 6.46 + 6.47 +void midi_out(uint8_t val) 6.48 +{ 6.49 + if (val & 0x80) 6.50 + { 6.51 + midi_pos = 0; 6.52 + midi_len = midi_lengths[(val >> 4) & 7]; 6.53 + midi_command = 0; 6.54 + } 6.55 + 6.56 + if (midi_len) 6.57 + { 6.58 + midi_command |= (val << (midi_pos * 8)); 6.59 + 6.60 + midi_pos++; 6.61 + 6.62 + if (midi_pos == midi_len) 6.63 + midiOutShortMsg(midi_out_device, midi_command); 6.64 + } 6.65 +}
7.1 --- a/src/win.c Mon May 27 19:56:33 2013 +0100 7.2 +++ b/src/win.c Tue Jun 04 20:52:17 2013 +0100 7.3 @@ -18,6 +18,7 @@ 7.4 #include "nvr.h" 7.5 #include "sound.h" 7.6 7.7 +#include "plat-midi.h" 7.8 #include "plat-keyboard.h" 7.9 7.10 #include "win-ddraw.h" 7.11 @@ -300,6 +301,8 @@ 7.12 ghwnd=hwnd; 7.13 7.14 ddraw_init(hwnd); 7.15 + midi_init(); 7.16 + atexit(midi_close); 7.17 // d3d_init(hwnd); 7.18 // opengl_init(hwnd); 7.19
