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