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.

This commit is contained in:
TomW 2013-06-04 20:52:17 +01:00
commit b9062a1d0c
7 changed files with 152 additions and 15 deletions

View file

@ -9,17 +9,17 @@ OBJ = 386.o 808x.o acer386sx.o ali1429.o amstrad.o cdrom-ioctl.o \
keyboard_olim24.o keyboard_xt.o lpt.o mcr.o mem.o model.o \
mouse.o mouse_ps2.o mouse_serial.o neat.o nvr.o olivetti_m24.o \
opti.o pc.o pci.o pic.o piix.o pit.o ppi.o serial.o sound.o sound_adlib.o \
sound_adlibgold.o sound_cms.o sound_gus.o sound_opl.o sound_pas16.o sound_sb.o \
sound_sb_dsp.o sound_sn76489.o sound_speaker.o sound_wss.o soundopenal.o timer.o \
um8881f.o um8669f.o vid_ati_eeprom.o vid_ati_mach64.o vid_ati18800.o \
vid_ati28800.o vid_ati68860_ramdac.o vid_cga.o vid_cl5429.o vid_ega.o \
vid_et4000.o vid_et4000w32.o vid_et4000w32i.o vid_hercules.o vid_icd2061.o \
vid_ics2595.o vid_mda.o vid_olivetti_m24.o vid_oti067.o vid_paradise.o \
vid_pc1512.o vid_pc1640.o vid_pc200.o vid_s3.o vid_s3_virge.o vid_sdac_ramdac.o \
vid_stg_ramdac.o vid_svga.o vid_svga_render.o vid_tandy.o vid_tkd8001_ramdac.o \
vid_tvga.o vid_unk_ramdac.o vid_vga.o vid_voodoo.o video.o wd76c10.o \
win.o win-ddraw.o win-keyboard.o win-mouse.o win-timer.o win-video.o \
x86seg.o x87.o xtide.o pc.res
sound_adlibgold.o sound_cms.o sound_gus.o sound_mpu401_uart.o sound_opl.o \
sound_pas16.o sound_sb.o sound_sb_dsp.o sound_sn76489.o sound_speaker.o \
sound_wss.o soundopenal.o timer.o um8881f.o um8669f.o vid_ati_eeprom.o \
vid_ati_mach64.o vid_ati18800.o vid_ati28800.o vid_ati68860_ramdac.o vid_cga.o \
vid_cl5429.o vid_ega.o vid_et4000.o vid_et4000w32.o vid_et4000w32i.o \
vid_hercules.o vid_icd2061.o vid_ics2595.o vid_mda.o vid_olivetti_m24.o \
vid_oti067.o vid_paradise.o vid_pc1512.o vid_pc1640.o vid_pc200.o vid_s3.o \
vid_s3_virge.o vid_sdac_ramdac.o vid_stg_ramdac.o vid_svga.o vid_svga_render.o \
vid_tandy.o vid_tkd8001_ramdac.o vid_tvga.o vid_unk_ramdac.o vid_vga.o \
vid_voodoo.o video.o wd76c10.o win.o win-ddraw.o win-keyboard.o win-midi.o \
win-mouse.o win-timer.o win-video.o x86seg.o x87.o xtide.o pc.res
FMOBJ = fmopl.o ymf262.o

3
src/plat-midi.h Normal file
View file

@ -0,0 +1,3 @@
void midi_init();
void midi_close();
void midi_out(uint8_t val);

57
src/sound_mpu401_uart.c Normal file
View file

@ -0,0 +1,57 @@
#include "ibm.h"
#include "io.h"
#include "sound_mpu401_uart.h"
enum
{
STATUS_OUTPUT_NOT_READY = 0x40,
STATUS_INPUT_NOT_READY = 0x80
};
static void mpu401_uart_write(uint16_t addr, uint8_t val, void *p)
{
mpu401_uart_t *mpu = (mpu401_uart_t *)p;
if (addr & 1) /*Command*/
{
switch (val)
{
case 0xff: /*Reset*/
mpu->rx_data = 0xfe; /*Acknowledge*/
mpu->status = 0;
mpu->uart_mode = 0;
break;
case 0x3f: /*Enter UART mode*/
mpu->rx_data = 0xfe; /*Acknowledge*/
mpu->status = 0;
mpu->uart_mode = 1;
break;
}
return;
}
/*Data*/
if (mpu->uart_mode)
midi_out(val);
}
static uint8_t mpu401_uart_read(uint16_t addr, void *p)
{
mpu401_uart_t *mpu = (mpu401_uart_t *)p;
if (addr & 1) /*Status*/
return mpu->status;
/*Data*/
mpu->status |= STATUS_INPUT_NOT_READY;
return mpu->rx_data;
}
void mpu401_uart_init(mpu401_uart_t *mpu, uint16_t addr)
{
mpu->status = STATUS_INPUT_NOT_READY;
mpu->uart_mode = 0;
io_sethandler(addr, 0x0002, mpu401_uart_read, NULL, NULL, mpu401_uart_write, NULL, NULL, mpu);
}

9
src/sound_mpu401_uart.h Normal file
View file

@ -0,0 +1,9 @@
typedef struct mpu401_uart_t
{
uint8_t status;
uint8_t rx_data;
int uart_mode;
} mpu401_uart_t;
void mpu401_uart_init(mpu401_uart_t *mpu, uint16_t addr);

View file

@ -1,9 +1,10 @@
#include <stdlib.h>
#include "ibm.h"
#include "device.h"
#include "sound_mpu401_uart.h"
#include "sound_opl.h"
#include "sound_sb.h"
#include "sound_sb_dsp.h"
#include "sound_opl.h"
#include "filters.h"
@ -22,9 +23,10 @@ typedef struct sb_mixer_t
typedef struct sb_t
{
opl_t opl;
sb_dsp_t dsp;
sb_mixer_t mixer;
opl_t opl;
sb_dsp_t dsp;
sb_mixer_t mixer;
mpu401_uart_t mpu;
int16_t opl_buffer[SOUNDBUFLEN * 2];
int16_t dsp_buffer[SOUNDBUFLEN * 2];
@ -336,6 +338,7 @@ void *sb_16_init()
io_sethandler(0x0388, 0x0002, opl3_read, NULL, NULL, opl3_write, NULL, NULL, &sb->opl);
io_sethandler(0x0224, 0x0002, sb_16_mixer_read, NULL, NULL, sb_16_mixer_write, NULL, NULL, sb);
sound_add_handler(sb_opl3_poll, sb_get_buffer, sb);
mpu401_uart_init(&sb->mpu, 0x330);
sb->mixer.regs[0x30] = 31 << 3;
sb->mixer.regs[0x31] = 31 << 3;

62
src/win-midi.c Normal file
View file

@ -0,0 +1,62 @@
#include <windows.h>
#include <mmsystem.h>
#include "ibm.h"
#include "plat-midi.h"
static int midi_id;
static HMIDIOUT midi_out_device = NULL;
void midi_close();
void midi_init()
{
int c;
int n;
MIDIOUTCAPS ocaps;
MMRESULT hr;
midi_id=0;
hr = midiOutOpen(&midi_out_device, midi_id, 0,
0, CALLBACK_NULL);
if (hr != MMSYSERR_NOERROR) {
printf("midiOutOpen error - %08X\n",hr);
return;
}
midiOutReset(midi_out_device);
}
void midi_close()
{
if (midi_out_device != NULL)
{
midiOutReset(midi_out_device);
midiOutClose(midi_out_device);
midi_out_device = NULL;
}
}
static int midi_pos, midi_len;
static uint32_t midi_command;
static int midi_lengths[8] = {3, 3, 3, 3, 2, 2, 3, 0};
void midi_out(uint8_t val)
{
if (val & 0x80)
{
midi_pos = 0;
midi_len = midi_lengths[(val >> 4) & 7];
midi_command = 0;
}
if (midi_len)
{
midi_command |= (val << (midi_pos * 8));
midi_pos++;
if (midi_pos == midi_len)
midiOutShortMsg(midi_out_device, midi_command);
}
}

View file

@ -18,6 +18,7 @@
#include "nvr.h"
#include "sound.h"
#include "plat-midi.h"
#include "plat-keyboard.h"
#include "win-ddraw.h"
@ -300,6 +301,8 @@ int WINAPI WinMain (HINSTANCE hThisInstance,
ghwnd=hwnd;
ddraw_init(hwnd);
midi_init();
atexit(midi_close);
// d3d_init(hwnd);
// opengl_init(hwnd);