diff --git a/src/Makefile.am b/src/Makefile.am index 4bf80a1..007989a 100644 --- a/src/Makefile.am +++ b/src/Makefile.am @@ -24,7 +24,7 @@ keyboard.c keyboard_amstrad.c keyboard_at.c keyboard_olim24.c keyboard_pcjr.c ke linux-time.c lpt.c mcr.c mem.c model.c mouse.c mouse_ps2.c mouse_serial.c neat.c nmi.c nvr.c \ olivetti_m24.c opti.c pc.c pci.c pic.c piix.c pit.c ppi.c ps1.c rom.c serial.c sis496.c sound.c \ sound_ad1848.c sound_adlib.c sound_adlibgold.c sound_cms.c sound_emu8k.c sound_gus.c \ -sound_mpu401_uart.c sound_opl.c sound_pas16.c sound_pssj.c sound_sb.c sound_sb_dsp.c sound_sn76489.c \ +sound_mpu401_uart.c sound_opl.c sound_pas16.c sound_ps1.c sound_pssj.c sound_sb.c sound_sb_dsp.c sound_sn76489.c \ sound_speaker.c sound_ssi2001.c sound_wss.c sound_ym7128.c soundopenal.c tandy_eeprom.c tandy_rom.c thread-pthread.c \ timer.c um8669f.c um8881f.c vid_ati_eeprom.c vid_ati_mach64.c vid_ati18800.c vid_ati28800.c \ vid_ati68860_ramdac.c vid_cga.c vid_cl5429.c vid_ega.c vid_et4000.c vid_et4000w32.c vid_hercules.c \ diff --git a/src/Makefile.mingw b/src/Makefile.mingw index 9812ed0..6db4caf 100644 --- a/src/Makefile.mingw +++ b/src/Makefile.mingw @@ -10,7 +10,7 @@ OBJ = 386.o 386_dynarec.o 386_dynarec_ops.o 808x.o acer386sx.o ali1429.o amstrad keyboard_olim24.o keyboard_pcjr.o keyboard_xt.o lpt.o mcr.o mem.o model.o mouse.o mouse_ps2.o \ mouse_serial.o neat.o nmi.o nvr.o olivetti_m24.o opti.o pc.o pci.o pic.o piix.o pit.o ppi.o ps1.o rom.o \ serial.o sis496.o sound.o sound_ad1848.o sound_adlib.o sound_adlibgold.o sound_cms.o sound_dbopl.o \ - sound_emu8k.o sound_gus.o sound_mpu401_uart.o sound_opl.o sound_pas16.o sound_pssj.o sound_resid.o \ + sound_emu8k.o sound_gus.o sound_mpu401_uart.o sound_opl.o sound_pas16.o sound_ps1.o sound_pssj.o sound_resid.o \ sound_sb.o sound_sb_dsp.o sound_sn76489.o sound_speaker.o sound_ssi2001.o sound_wss.o \ sound_ym7128.o soundopenal.o tandy_eeprom.o tandy_rom.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 \ diff --git a/src/Makefile.mingw64 b/src/Makefile.mingw64 index d5dfcbd..577293c 100644 --- a/src/Makefile.mingw64 +++ b/src/Makefile.mingw64 @@ -10,7 +10,7 @@ OBJ = 386.o 386_dynarec.o 386_dynarec_ops.o 808x.o acer386sx.o ali1429.o amstrad keyboard_olim24.o keyboard_pcjr.o keyboard_xt.o lpt.o mcr.o mem.o model.o mouse.o mouse_ps2.o \ mouse_serial.o neat.o nmi.o nvr.o olivetti_m24.o opti.o pc.o pci.o pic.o piix.o pit.o ppi.o ps1.o rom.o \ serial.o sis496.o sound.o sound_ad1848.o sound_adlib.o sound_adlibgold.o sound_cms.o sound_dbopl.o \ - sound_emu8k.o sound_gus.o sound_mpu401_uart.o sound_opl.o sound_pas16.o sound_pssj.o sound_resid.o \ + sound_emu8k.o sound_gus.o sound_mpu401_uart.o sound_opl.o sound_pas16.o sound_ps1.o sound_pssj.o sound_resid.o \ sound_sb.o sound_sb_dsp.o sound_sn76489.o sound_speaker.o sound_ssi2001.o sound_wss.o sound_ym7128.o \ soundopenal.o tandy_eeprom.o tandy_rom.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 \ diff --git a/src/cpu.h b/src/cpu.h index 8492d3c..4f7c080 100644 --- a/src/cpu.h +++ b/src/cpu.h @@ -1,3 +1,6 @@ +#ifndef _CPU_H_ +#define _CPU_H_ + extern int cpu, cpu_manufacturer; /*808x class CPUs*/ @@ -111,3 +114,5 @@ void cpu_WRMSR(); extern int cpu_use_dynarec; extern int xt_cpu_multi; + +#endif diff --git a/src/gameport.c b/src/gameport.c index dc45ec5..c6cd9f3 100644 --- a/src/gameport.c +++ b/src/gameport.c @@ -90,7 +90,7 @@ void gameport_timer_over(void *p) // pclog("gameport_timer_over : axis_nr=%i\n", axis->axis_nr); } -void *gameport_init() +void *gameport_init_common() { gameport_t *gameport = malloc(sizeof(gameport_t)); @@ -110,9 +110,25 @@ void *gameport_init() timer_add(gameport_timer_over, &gameport->axis[1].count, &gameport->axis[1].count, &gameport->axis[1]); timer_add(gameport_timer_over, &gameport->axis[2].count, &gameport->axis[2].count, &gameport->axis[2]); timer_add(gameport_timer_over, &gameport->axis[3].count, &gameport->axis[3].count, &gameport->axis[3]); - + + return gameport; +} + +void *gameport_init() +{ + gameport_t *gameport = gameport_init_common(); + io_sethandler(0x0200, 0x0008, gameport_read, NULL, NULL, gameport_write, NULL, NULL, gameport); - + + return gameport; +} + +void *gameport_201_init() +{ + gameport_t *gameport = gameport_init_common(); + + io_sethandler(0x0201, 0x0001, gameport_read, NULL, NULL, gameport_write, NULL, NULL, gameport); + return gameport; } @@ -134,3 +150,15 @@ device_t gameport_device = NULL, NULL }; + +device_t gameport_201_device = +{ + "Game port (port 201h only)", + 0, + gameport_201_init, + gameport_close, + NULL, + NULL, + NULL, + NULL +}; diff --git a/src/gameport.h b/src/gameport.h index 6884490..71c73a7 100644 --- a/src/gameport.h +++ b/src/gameport.h @@ -1 +1,2 @@ extern device_t gameport_device; +extern device_t gameport_201_device; diff --git a/src/model.c b/src/model.c index adc3b70..bef0f98 100644 --- a/src/model.c +++ b/src/model.c @@ -39,6 +39,7 @@ #include "ps1.h" #include "serial.h" #include "sis496.h" +#include "sound_ps1.h" #include "sound_pssj.h" #include "sound_sn76489.h" #include "tandy_eeprom.h" @@ -154,7 +155,6 @@ void common_init() pit_init(); serial1_init(0x3f8, 4); serial2_init(0x2f8, 3); - device_add(&gameport_device); } void xt_init() @@ -166,6 +166,7 @@ void xt_init() mouse_serial_init(); xtide_init(); nmi_init(); + device_add(&gameport_device); } void pcjr_init() @@ -196,6 +197,7 @@ void tandy1k_init() nmi_init(); if (romset != ROM_TANDY) device_add(&tandy_eeprom_device); + device_add(&gameport_device); } void tandy1ksl2_init() { @@ -209,6 +211,7 @@ void tandy1ksl2_init() nmi_init(); device_add(&tandy_rom_device); device_add(&tandy_eeprom_device); + device_add(&gameport_device); } void ams_init() @@ -222,6 +225,7 @@ void ams_init() xtide_init(); nmi_init(); fdc_set_dskchg_activelow(); + device_add(&gameport_device); } void europc_init() @@ -233,6 +237,7 @@ void europc_init() mouse_serial_init(); xtide_init(); nmi_init(); + device_add(&gameport_device); } void olim24_init() @@ -244,6 +249,7 @@ void olim24_init() olivetti_m24_init(); xtide_init(); nmi_init(); + device_add(&gameport_device); } void at_init() @@ -259,6 +265,7 @@ void at_init() mouse_serial_init(); nvr_init(); pic2_init(); + device_add(&gameport_device); } void deskpro386_init() @@ -282,6 +289,9 @@ void ps1_init() pic2_init(); ps1mb_init(); fdc_set_dskchg_activelow(); + device_add(&ps1_audio_device); + /*PS/1 audio uses ports 200h and 202-207h, so only initialise gameport on 201h*/ + device_add(&gameport_201_device); } void at_neat_init() diff --git a/src/sound_ps1.c b/src/sound_ps1.c new file mode 100644 index 0000000..17b3d7f --- /dev/null +++ b/src/sound_ps1.c @@ -0,0 +1,174 @@ +#include +#include "ibm.h" +#include "device.h" +#include "io.h" +#include "sound.h" +#include "sound_ps1.h" +#include "sound_sn76489.h" + +typedef struct ps1_audio_t +{ + sn76489_t sn76489; + + uint8_t status, ctrl; + + int timer_latch, timer_count, timer_enable; + + uint8_t fifo[2048]; + int fifo_read_idx, fifo_write_idx; + int fifo_threshold; + + uint8_t dac_val; + + int16_t buffer[SOUNDBUFLEN]; + int pos; +} ps1_audio_t; + +static void ps1_update_irq_status(ps1_audio_t *ps1) +{ + if (((ps1->status & ps1->ctrl) & 0x12) && (ps1->ctrl & 0x01)) + picint(1 << 7); + else + picintc(1 << 7); +} + +static uint8_t ps1_audio_read(uint16_t port, void *p) +{ + ps1_audio_t *ps1 = (ps1_audio_t *)p; + uint8_t temp; + +// pclog("ps1_audio_read %04x %04x:%04x\n", port, CS, pc); + + switch (port & 7) + { + case 0: /*ADC data*/ + ps1->status &= ~0x10; + ps1_update_irq_status(ps1); + return 0; + case 2: /*Status*/ + temp = ps1->status; + temp |= (ps1->ctrl & 0x01); + if ((ps1->fifo_write_idx - ps1->fifo_read_idx) >= 2048) + temp |= 0x08; /*FIFO full*/ + if (ps1->fifo_read_idx == ps1->fifo_write_idx) + temp |= 0x04; /*FIFO empty*/ +// pclog("Return status %02x\n", temp); + return temp; + case 3: /*FIFO timer*/ + /*PS/1 technical reference says this should return the current value, + but the PS/1 BIOS and Stunt Island expect it not to change*/ + return ps1->timer_latch; + case 4: case 5: case 6: case 7: + return 0; + } + return 0xff; +} + +static void ps1_audio_write(uint16_t port, uint8_t val, void *p) +{ + ps1_audio_t *ps1 = (ps1_audio_t *)p; + +// pclog("ps1_audio_write %04x %02x\n", port, val); + + switch (port & 7) + { + case 0: /*DAC output*/ +// pclog("DAC write %08x %08x %i\n", ps1->fifo_write_idx, ps1->fifo_read_idx, ps1->fifo_write_idx - ps1->fifo_read_idx); + if ((ps1->fifo_write_idx - ps1->fifo_read_idx) < 2048) + { + ps1->fifo[ps1->fifo_write_idx & 2047] = val; + ps1->fifo_write_idx++; + } + break; + case 2: /*Control*/ + ps1->ctrl = val; + if (!(val & 0x02)) + ps1->status &= ~0x02; + ps1_update_irq_status(ps1); + break; + case 3: /*Timer reload value*/ + ps1->timer_latch = val; + ps1->timer_count = (0xff-val) * TIMER_USEC; + ps1->timer_enable = (val != 0); + break; + case 4: /*Almost empty*/ + ps1->fifo_threshold = val * 4; + break; + } +} + +static void ps1_audio_update(ps1_audio_t *ps1) +{ + for (; ps1->pos < sound_pos_global; ps1->pos++) + ps1->buffer[ps1->pos] = (int8_t)(ps1->dac_val ^ 0x80) * 0x20; +} + +static void ps1_audio_callback(void *p) +{ + ps1_audio_t *ps1 = (ps1_audio_t *)p; + + ps1_audio_update(ps1); + + if (ps1->fifo_read_idx != ps1->fifo_write_idx) + { + ps1->dac_val = ps1->fifo[ps1->fifo_read_idx & 2047]; + ps1->fifo_read_idx++; + } +// pclog("ps1_callback %08x %08x %08x\n", ps1->fifo_write_idx, ps1->fifo_read_idx, ps1->fifo_threshold); + if ((ps1->fifo_write_idx - ps1->fifo_read_idx) == ps1->fifo_threshold) + { +// pclog("FIFO almost empty\n"); + ps1->status |= 0x02; /*FIFO almost empty*/ + } + ps1->status |= 0x10; /*ADC data ready*/ + ps1_update_irq_status(ps1); + + ps1->timer_count += ps1->timer_latch * TIMER_USEC; +} + +static void ps1_audio_get_buffer(int16_t *buffer, int len, void *p) +{ + ps1_audio_t *ps1 = (ps1_audio_t *)p; + int c; + + ps1_audio_update(ps1); + + for (c = 0; c < len * 2; c++) + buffer[c] += ps1->buffer[c >> 1]; + + ps1->pos = 0; +} + +static void *ps1_audio_init() +{ + ps1_audio_t *ps1 = malloc(sizeof(ps1_audio_t)); + memset(ps1, 0, sizeof(ps1_audio_t)); + + sn76489_init(&ps1->sn76489, 0x0205, 0x0001, SN76496, 4000000); + + io_sethandler(0x0200, 0x0001, ps1_audio_read, NULL, NULL, ps1_audio_write, NULL, NULL, ps1); + io_sethandler(0x0202, 0x0006, ps1_audio_read, NULL, NULL, ps1_audio_write, NULL, NULL, ps1); + timer_add(ps1_audio_callback, &ps1->timer_count, &ps1->timer_enable, ps1); + sound_add_handler(ps1_audio_get_buffer, ps1); + + return ps1; +} + +static void ps1_audio_close(void *p) +{ + ps1_audio_t *ps1 = (ps1_audio_t *)p; + + free(ps1); +} + +device_t ps1_audio_device = +{ + "PS/1 Audio Card", + 0, + ps1_audio_init, + ps1_audio_close, + NULL, + NULL, + NULL, + NULL +}; diff --git a/src/sound_ps1.h b/src/sound_ps1.h new file mode 100644 index 0000000..7dcb093 --- /dev/null +++ b/src/sound_ps1.h @@ -0,0 +1 @@ +extern device_t ps1_audio_device; diff --git a/src/sound_pssj.c b/src/sound_pssj.c index 06702a9..7443319 100644 --- a/src/sound_pssj.c +++ b/src/sound_pssj.c @@ -185,7 +185,7 @@ void *pssj_init() pssj_t *pssj = malloc(sizeof(pssj_t)); memset(pssj, 0, sizeof(pssj_t)); - sn76489_init(&pssj->sn76489, 0x00c0, 0x0004, PSSJ); + sn76489_init(&pssj->sn76489, 0x00c0, 0x0004, PSSJ, 3579545); io_sethandler(0x00C4, 0x0004, pssj_read, NULL, NULL, pssj_write, NULL, NULL, pssj); timer_add(pssj_callback, &pssj->timer_count, &pssj->enable, pssj); diff --git a/src/sound_sn76489.c b/src/sound_sn76489.c index 1f4d559..b495e9f 100644 --- a/src/sound_sn76489.c +++ b/src/sound_sn76489.c @@ -15,7 +15,7 @@ static float volslog[16]= 7.51785f,9.46440f,11.9194f,15.0000f }; -#define PSGCONST ((3579545.0 / 64.0) / 48000.0) +//#define PSGCONST ((3579545.0 / 64.0) / 48000.0) void sn76489_update(sn76489_t *sn76489) { @@ -29,7 +29,7 @@ void sn76489_update(sn76489_t *sn76489) if (sn76489->latch[c] > 256) result += (int16_t) (volslog[sn76489->vol[c]] * sn76489->stat[c]); else result += (int16_t) (volslog[sn76489->vol[c]] * 127); - sn76489->count[c] -= (256 * PSGCONST); + sn76489->count[c] -= (256 * sn76489->psgconst); while ((int)sn76489->count[c] < 0) { sn76489->count[c] += sn76489->latch[c]; @@ -38,7 +38,7 @@ void sn76489_update(sn76489_t *sn76489) } result += (((sn76489->shift & 1) ^ 1) * 127 * volslog[sn76489->vol[0]] * 2); - sn76489->count[0] -= (512 * PSGCONST); + sn76489->count[0] -= (512 * sn76489->psgconst); while ((int)sn76489->count[0] < 0 && sn76489->latch[0]) { sn76489->count[0] += (sn76489->latch[0] * 4); @@ -177,7 +177,7 @@ void sn74689_set_extra_divide(sn76489_t *sn76489, int enable) sn76489->extra_divide = enable; } -void sn76489_init(sn76489_t *sn76489, uint16_t base, uint16_t size, int type) +void sn76489_init(sn76489_t *sn76489, uint16_t base, uint16_t size, int type, int freq) { sound_add_handler(sn76489_get_buffer, sn76489); @@ -193,6 +193,7 @@ void sn76489_init(sn76489_t *sn76489, uint16_t base, uint16_t size, int type) sn76489->noise = 3; sn76489->shift = 0x4000; sn76489->type = type; + sn76489->psgconst = (((double)freq / 64.0) / 48000.0); sn76489_mute = 0; @@ -204,7 +205,7 @@ void *sn76489_device_init() sn76489_t *sn76489 = malloc(sizeof(sn76489_t)); memset(sn76489, 0, sizeof(sn76489_t)); - sn76489_init(sn76489, 0x00c0, 0x0008, SN76496); + sn76489_init(sn76489, 0x00c0, 0x0008, SN76496, 3579545); return sn76489; } @@ -213,7 +214,7 @@ void *ncr8496_device_init() sn76489_t *sn76489 = malloc(sizeof(sn76489_t)); memset(sn76489, 0, sizeof(sn76489_t)); - sn76489_init(sn76489, 0x00c0, 0x0008, NCR8496); + sn76489_init(sn76489, 0x00c0, 0x0008, NCR8496, 3579545); return sn76489; } diff --git a/src/sound_sn76489.h b/src/sound_sn76489.h index b311e0f..2f7a687 100644 --- a/src/sound_sn76489.h +++ b/src/sound_sn76489.h @@ -25,7 +25,9 @@ typedef struct sn76489_t int16_t buffer[SOUNDBUFLEN]; int pos; + + double psgconst; } sn76489_t; -void sn76489_init(sn76489_t *sn76489, uint16_t base, uint16_t size, int type); +void sn76489_init(sn76489_t *sn76489, uint16_t base, uint16_t size, int type, int freq); void sn74689_set_extra_divide(sn76489_t *sn76489, int enable); diff --git a/src/timer.h b/src/timer.h index b695969..43722d8 100644 --- a/src/timer.h +++ b/src/timer.h @@ -1,6 +1,8 @@ #ifndef _TIMER_H_ #define _TIMER_H_ +#include "cpu.h" + extern int timer_start; #define timer_start_period(cycles) \